home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume6 / less2 / part1 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  69.6 KB

  1. Subject:  v06i102:  New version of less (less2), Part01/02
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: seismo!lll-crg!csustan!casey
  6. Mod.sources: Volume 6, Issue 102
  7. Archive-name: less2/Part01
  8.  
  9. [  This version of less provides support for "boldening," as in a^Ha^Ha,
  10.    and a "-z" flag to set the window size (for compatiblity with more).
  11.    It also provides a small front-end program for systems/programs that
  12.    don't support the PAGER environment variable.  And, as Casey said in
  13.    his cover note to me... "If you can find Mark Nudelman, send him a copy."
  14.    --r$  ]
  15.  
  16. ---- cut here ---- cut here ---- cut here ---- cut here ---- cut here ----
  17. #! /bin/sh
  18. # This is a shell archive, meaning:
  19. # 1. Remove everything above the #! /bin/sh line.
  20. # 2. Save the resulting text in a file.
  21. # 3. Execute the file with /bin/sh (not csh) to create:
  22. #    INSTALLATION
  23. #    README-casey
  24. #    README-usenet
  25. #    ch.c
  26. #    command.c
  27. #    funcs.h
  28. #    help.c
  29. #    input.c
  30. #    less.h
  31. #    less.l
  32. #    line.c
  33. #    main.c
  34. #    makefile.bsd41
  35. #    makefile.bsd42
  36. export PATH; PATH=/bin:/usr/bin:$PATH
  37. if test -f 'INSTALLATION'
  38. then
  39.     echo shar: "will not over-write existing file 'INSTALLATION'"
  40. else
  41. cat << \SHAR_EOF > 'INSTALLATION'
  42. This is the distribution of "less", a paginator similar to "more" or "pg".
  43. The manual page is in less.l.
  44.  
  45. INSTALLATION:
  46.  
  47. 1. Move the distributed source to its own directory and 
  48.    unpack it by running "sh" on the distribution file,
  49.    if you have not already done so.
  50.  
  51. 2. If your system is System V:
  52.     cp makefile.sys5 makefile
  53.    If your system is Berkeley 4.2bsd:
  54.     cp makefile.bsd42 makefile
  55.    If your system is Berkeley 4.1bsd:
  56.     cp makefile.bsd41 makefile
  57.    If your system is Xenix 3.0:
  58.     cp makefile.xen makefile
  59.    Otherwise, edit the makefile to make the 
  60.    system parameters match your system.
  61.  
  62.    These features are selectable at compile time:
  63.     shell escapes (SHELL_ESCAPE)
  64.     editor invocation (EDITOR)
  65.     alternate error message handling (ONLY_RETURN)
  66.    If you want to have any of these features, 
  67.    edit the makefile appropriately.
  68.    (If you do not include either SHELL_ESCAPE or EDITOR,
  69.     you may wish to edit the manual page "less.l" to remove
  70.     the references to the "!" and/or "v" commands.)
  71.  
  72. 3. Type "make" and watch the fun.
  73.  
  74. 4. If the make succeeds, it will generate a program "less"
  75.    in your current directory.  Test the generated program.
  76.  
  77. 5. When satisfied that it works, if you wish to install it
  78.    in a public place, edit the makefile so that INSTALL_LESS
  79.    and INSTALL_MAN are the proper filenames.
  80.    Then type "make install".
  81.  
  82. If you have any problems building or running "less", 
  83. you may mail to the author via USENET at:
  84.     ...!tektronix!reed!nsc-pdc!mark
  85.   or    ...!ihnp4!nsc!nsc-pdc!mark
  86.  
  87. Note to hackers: comments noting possible improvements are enclosed
  88. in double curly brackets {{ like this }}.
  89. SHAR_EOF
  90. fi
  91. if test -f 'README-casey'
  92. then
  93.     echo shar: "will not over-write existing file 'README-casey'"
  94. else
  95. cat << \SHAR_EOF > 'README-casey'
  96.                         Monday July 14, 1986
  97.  
  98. I've made four changes to less:
  99.  
  100. 1.    You can now install the pager_patch program to let you use less as
  101.     your default pager even if the programs you're using don't pay
  102.     attention to the PAGER environment variable.
  103.  
  104. 2.    It's now allowable to invoke less with "-[z]N" to specify the window
  105.     scroll size ala more (note that the "z" may be omitted) - this
  106.     was done for compatibility with more(1) as some programs (ex: msgs)
  107.     called the pager with a window size specification.
  108.  
  109. 3.    Less will now detect "boldfacing sequences" and use the /etc/termcap
  110.     capability "md" and "me" to boldface the corresponding text.
  111.     Boldface sequences are sequences of a character overstruck with
  112.     backspaces (ex: a^Hab^Hb ...).  Any number of overstrikes are ok.
  113.     For those whose nroff doesn't generate these sequences for [default]
  114.     boldfacing, look at the file n10-diff for the necessary changes to
  115.     nroff [n10.c].
  116.  
  117. 4.    The manual page has been reformatted to have more boldface sequences
  118.     (some may find my avoidance of ".B", ".I", etc. to be annoying, but
  119.     what the hey, I'll let Mark Nudelman (less's original author) have
  120.     the final decision).  I haven't reorganized the command and switch
  121.     descriptions to be in alphabetic order ...  Still not sure whether
  122.     that should be done ...
  123.  
  124. Leith (Casey) Leedom                lll-crg.arpa!csustan!casey
  125. Computer Science Department            work: (209) 667-3185
  126. California State University, Stanislaus        home: (209) 634-2775
  127. Turlock, CA  95380
  128. SHAR_EOF
  129. fi
  130. if test -f 'README-usenet'
  131. then
  132.     echo shar: "will not over-write existing file 'README-usenet'"
  133. else
  134. cat << \SHAR_EOF > 'README-usenet'
  135. >From sources-request@panda.UUCP Tue Feb 11 15:30:56 1986
  136. Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site lll-crg.ARpA
  137. Path: lll-crg!topaz!harvard!talcott!panda!sources-request
  138. From: sources-request@panda.UUCP
  139. Newsgroups: mod.sources
  140. Subject: less part 1 of 2
  141. Message-ID: <1400@panda.UUCP>
  142. Date: 11 Feb 86 23:30:56 GMT
  143. Date-Received: 12 Feb 86 05:00:57 GMT
  144. Sender: jpn@panda.UUCP
  145. Lines: 2500
  146. Approved: jpn@panda.UUCP
  147.  
  148. Mod.sources:  Volume 3, Issue 120
  149. Submitted by: ihnp4!nsc!nsc-pdc!rgb (Robert Bond)
  150.  
  151.  
  152.  
  153. Here is the last distribution of less made by Mark Nudelman to net.sources
  154. before he left National Semiconductor.  Since it is taking so long for him
  155. to get back on the net, and because lots of folks did not get part 2
  156. of the last distribution, we have decided to submit less to mod.sources.
  157. Mark is still promising to return to the net Real Soon Now.
  158. SHAR_EOF
  159. fi
  160. if test -f 'ch.c'
  161. then
  162.     echo shar: "will not over-write existing file 'ch.c'"
  163. else
  164. cat << \SHAR_EOF > 'ch.c'
  165. /*
  166.  * Low level character input from the input file.
  167.  * We use these special purpose routines which optimize moving
  168.  * both forward and backward from the current read pointer.
  169.  */
  170.  
  171. #include "less.h"
  172.  
  173. public int file = -1;    /* File descriptor of the input file */
  174.  
  175. /*
  176.  * Pool of buffers holding the most recently used blocks of the input file.
  177.  */
  178. #define BUFSIZ    1024
  179. static struct buf {
  180.     struct buf *next, *prev;
  181.     long block;
  182.     char data[BUFSIZ];
  183. };
  184. static struct buf *bufs = NULL;
  185. public int nbufs;
  186.  
  187. /*
  188.  * The buffer pool is kept as a doubly-linked circular list,
  189.  * in order from most- to least-recently used.
  190.  * The circular list is anchored by buf_anchor.
  191.  */
  192. static struct {
  193.     struct buf *next, *prev;
  194. } buf_anchor;
  195. #define    END_OF_CHAIN    ((struct buf *)&buf_anchor)
  196. #define    buf_head    buf_anchor.next
  197. #define    buf_tail    buf_anchor.prev
  198.  
  199. /*
  200.  * If we fail to allocate enough memory for buffers, we try to limp
  201.  * along with a minimum number of buffers.  
  202.  */
  203. #define    DEF_NBUFS    2    /* Minimum number of buffers */
  204.  
  205. extern int clean_data;
  206. extern int ispipe;
  207.  
  208. /*
  209.  * Current position in file.
  210.  * Stored as a block number and an offset into the block.
  211.  */
  212. static long ch_block;
  213. static int ch_offset;
  214.  
  215. /* 
  216.  * Length of file, needed if input is a pipe.
  217.  */
  218. static POSITION ch_fsize;
  219.  
  220. /*
  221.  * Largest block number read if input is standard input (a pipe).
  222.  */
  223. static long last_piped_block;
  224.  
  225. /*
  226.  * Get the character pointed to by the read pointer.
  227.  * ch_get() is a macro which is more efficient to call
  228.  * than fch_get (the function), in the usual case 
  229.  * that the block desired is at the head of the chain.
  230.  */
  231. #define    ch_get()   ((buf_head->block == ch_block) ? \
  232.             buf_head->data[ch_offset] : fch_get())
  233.     static int
  234. fch_get()
  235. {
  236.     register struct buf *bp;
  237.     register int n;
  238.     register int end;
  239.     POSITION pos;
  240.  
  241.     /*
  242.      * Look for a buffer holding the desired block.
  243.      */
  244.     for (bp = buf_head;  bp != END_OF_CHAIN;  bp = bp->next)
  245.         if (bp->block == ch_block)
  246.             goto found;
  247.     /*
  248.      * Block is not in a buffer.  
  249.      * Take the least recently used buffer 
  250.      * and read the desired block into it.
  251.      */
  252.     bp = buf_tail;
  253.     bp->block = ch_block;
  254.     pos = ch_block * BUFSIZ;
  255.     if (ispipe)
  256.     {
  257.         /*
  258.          * The block requested should be one more than
  259.          * the last block read.
  260.          */
  261.         if (ch_block != ++last_piped_block)
  262.         {
  263.             /* This "should not happen". */
  264.             char message[80];
  265.             sprintf(message, "Pipe error: last %ld, want %ld\n",
  266.                 last_piped_block-1, ch_block);
  267.             error(message);
  268.             quit();
  269.         }
  270.     } else
  271.         lseek(file, pos, 0);
  272.  
  273.     /*
  274.      * Read the block.  This may take several reads if the input
  275.      * is coming from standard input, due to the nature of pipes.
  276.      */
  277.     end = 0;
  278.     while ((n = read(file, &bp->data[end], BUFSIZ-end)) > 0)
  279.         if ((end += n) >= BUFSIZ)
  280.             break;
  281.  
  282.     if (n < 0)
  283.     {
  284.         error("read error");
  285.         quit();
  286.     }
  287.  
  288.     /*
  289.      * Set an EOF marker in the buffered data itself.
  290.      * Then ensure the data is "clean": there are no 
  291.      * extra EOF chars in the data and that the "meta"
  292.      * bit (the 0200 bit) is reset in each char.
  293.      */
  294.     if (end < BUFSIZ)
  295.     {
  296.         ch_fsize = pos + end;
  297.         bp->data[end] = EOF;
  298.     }
  299.  
  300.     if (!clean_data)
  301.         while (--end >= 0)
  302.         {
  303.             bp->data[end] &= 0177;
  304.             if (bp->data[end] == EOF)
  305.                 bp->data[end] = '@';
  306.         }
  307.  
  308.     found:
  309.     /* if (buf_head != bp) {this is guaranteed by the ch_get macro} */
  310.     {
  311.         /*
  312.          * Move the buffer to the head of the buffer chain.
  313.          * This orders the buffer chain, most- to least-recently used.
  314.          */
  315.         bp->next->prev = bp->prev;
  316.         bp->prev->next = bp->next;
  317.  
  318.         bp->next = buf_head;
  319.         bp->prev = END_OF_CHAIN;
  320.         buf_head->prev = bp;
  321.         buf_head = bp;
  322.     }
  323.     return (bp->data[ch_offset]);
  324. }
  325.  
  326. /*
  327.  * Determine if a specific block is currently in one of the buffers.
  328.  */
  329.     static int
  330. buffered(block)
  331.     long block;
  332. {
  333.     register struct buf *bp;
  334.  
  335.     for (bp = buf_head;  bp != END_OF_CHAIN;  bp = bp->next)
  336.         if (bp->block == block)
  337.             return (1);
  338.     return (0);
  339. }
  340.  
  341. /*
  342.  * Seek to a specified position in the file.
  343.  * Return 0 if successful, non-zero if can't seek there.
  344.  */
  345.     public int
  346. ch_seek(pos)
  347.     register POSITION pos;
  348. {
  349.     long new_block;
  350.  
  351.     new_block = pos / BUFSIZ;
  352.     if (!ispipe || new_block == last_piped_block + 1 || buffered(new_block))
  353.     {
  354.         /*
  355.          * Set read pointer.
  356.          */
  357.         ch_block = new_block;
  358.         ch_offset = pos % BUFSIZ;
  359.         return (0);
  360.     }
  361.     return (1);
  362. }
  363.  
  364. /*
  365.  * Seek to the end of the file.
  366.  */
  367.     public int
  368. ch_end_seek()
  369. {
  370.     if (ispipe)
  371.     {
  372.         /*
  373.          * Do it the slow way: read till end of data.
  374.          */
  375.         while (ch_forw_get() != EOF)
  376.             ;
  377.     } else
  378.     {
  379.         (void) ch_seek((POSITION)(lseek(file, (off_t)0, 2)));
  380.     }
  381.     return (0);
  382. }
  383.  
  384. /*
  385.  * Return the length of the file, if known.
  386.  */
  387.     public POSITION
  388. ch_length()
  389. {
  390.     if (ispipe)
  391.         return (ch_fsize);
  392.     return ((POSITION)(lseek(file, (off_t)0, 2)));
  393. }
  394.  
  395. /*
  396.  * Return the current position in the file.
  397.  */
  398.     public POSITION
  399. ch_tell()
  400. {
  401.     return (ch_block * BUFSIZ + ch_offset);
  402. }
  403.  
  404. /*
  405.  * Get the current char and post-increment the read pointer.
  406.  */
  407.     public int
  408. ch_forw_get()
  409. {
  410.     register int c;
  411.  
  412.     c = ch_get();
  413.     if (c != EOF && ++ch_offset >= BUFSIZ)
  414.     {
  415.         ch_offset = 0;
  416.         ch_block ++;
  417.     }
  418.     return (c);
  419. }
  420.  
  421. /*
  422.  * Pre-decrement the read pointer and get the new current char.
  423.  */
  424.     public int
  425. ch_back_get()
  426. {
  427.     register int c;
  428.  
  429.     if (--ch_offset < 0)
  430.     {
  431.         if (ch_block <= 0 || (ispipe && !buffered(ch_block-1)))
  432.         {
  433.             ch_offset = 0;
  434.             return (EOF);
  435.         }
  436.         ch_offset = BUFSIZ - 1;
  437.         ch_block--;
  438.     }
  439.     c = ch_get();
  440.     return (c);
  441. }
  442.  
  443. /*
  444.  * Initialize the buffer pool to all empty.
  445.  * Caller suggests that we use want_nbufs buffers.
  446.  */
  447.     public void
  448. ch_init(want_nbufs)
  449.     int want_nbufs;
  450. {
  451.     register struct buf *bp;
  452.     char *calloc();
  453.  
  454.     if (nbufs < want_nbufs)
  455.     {
  456.         /*
  457.          * We don't have enough buffers.  
  458.          * Free what we have (if any) and allocate some new ones.
  459.          */
  460.         if (bufs != NULL)
  461.             free((char *)bufs);
  462.         bufs = (struct buf *) calloc(want_nbufs, sizeof(struct buf));
  463.         nbufs = want_nbufs;
  464.         if (bufs == NULL)
  465.         {
  466.             /*
  467.              * Couldn't get that many.
  468.              * Try for a small default number of buffers.
  469.              */
  470.             char message[80];
  471.             sprintf(message,
  472.               "Cannot allocate %d buffers.  Using %d buffers.", 
  473.               nbufs, DEF_NBUFS);
  474.             error(message);
  475.             bufs = (struct buf *) calloc(DEF_NBUFS, sizeof(struct buf));
  476.             nbufs = DEF_NBUFS;
  477.             if (bufs == NULL)
  478.             {
  479.                 /*
  480.                  * Couldn't even get the smaller number of bufs.
  481.                  * Something is wrong here, don't continue.
  482.                  */
  483.                 sprintf(message, 
  484.                 "Cannot even allocate %d buffers!  Quitting.\n",
  485.                   DEF_NBUFS);
  486.                 error(message);
  487.                 quit();
  488.                 /*NOTREACHED*/
  489.             }
  490.         }
  491.     }
  492.  
  493.     /*
  494.      * Initialize the buffers to empty.
  495.      * Set up the circular list.
  496.      */
  497.     for (bp = &bufs[0];  bp < &bufs[nbufs];  bp++)
  498.     {
  499.         bp->next = bp + 1;
  500.         bp->prev = bp - 1;
  501.         bp->block = (long)(-1);
  502.     }
  503.     bufs[0].prev = bufs[nbufs-1].next = END_OF_CHAIN;
  504.     buf_head = &bufs[0];
  505.     buf_tail = &bufs[nbufs-1];
  506.     last_piped_block = -1;
  507.     ch_fsize = NULL_POSITION;
  508.     (void) ch_seek((POSITION)0);
  509. }
  510. SHAR_EOF
  511. fi
  512. if test -f 'command.c'
  513. then
  514.     echo shar: "will not over-write existing file 'command.c'"
  515. else
  516. cat << \SHAR_EOF > 'command.c'
  517. /*
  518.  * User-level command processor.
  519.  */
  520.  
  521. #include "less.h"
  522. #include "position.h"
  523. #include <setjmp.h>
  524.  
  525. extern jmp_buf main_loop;
  526. extern int erase_char, kill_char;
  527. extern int pr_type;
  528. extern int sigs;
  529. extern int ispipe;
  530. extern int quit_at_eof;
  531. extern int hit_eof;
  532. extern int sc_width, sc_height;
  533. extern int sc_window;
  534. extern char *first_cmd;
  535. extern char version[];
  536. extern char current_file[];
  537. extern char *editor;
  538.  
  539. static char cmdbuf[90];        /* Buffer for holding a multi-char command */
  540. static char *cp;        /* Pointer into cmdbuf */
  541. static int cmd_col;        /* Current column of the multi-char command */
  542. static char mcc;        /* The multi-char command letter (e.g. '/') */
  543. static char last_mcc;        /* The previous mcc */
  544.  
  545. /*
  546.  * Reset command buffer (to empty).
  547.  */
  548. cmd_reset()
  549. {
  550.     cp = cmdbuf;
  551. }
  552.  
  553. /*
  554.  * Backspace in command buffer.
  555.  */
  556.     static int
  557. cmd_erase()
  558. {
  559.     if (cp == cmdbuf)
  560.         /*
  561.          * Backspace past beginning of the string:
  562.          * this usually means abort the command.
  563.          */
  564.         return (1);
  565.  
  566.     if (control_char(*--cp))
  567.     {
  568.         /*
  569.          * Erase an extra character, for the carat.
  570.          */
  571.         backspace();
  572.         cmd_col--;
  573.     }
  574.     backspace();
  575.     cmd_col--;
  576.     return (0);
  577. }
  578.  
  579. /*
  580.  * Set up the display to start a new multi-character command.
  581.  */
  582. start_mcc()
  583. {
  584.     lower_left();
  585.     clear_eol();
  586.     putc(mcc);
  587.     cmd_col = 1;
  588. }
  589.  
  590. /*
  591.  * Process a single character of a multi-character command, such as
  592.  * a number, or the pattern of a search command.
  593.  */
  594.     static int
  595. cmd_char(c)
  596.     int c;
  597. {
  598.     if (c == erase_char)
  599.     {
  600.         if (cmd_erase())
  601.             return (1);
  602.     } else if (c == kill_char)
  603.     {
  604.         /* {{ Could do this faster, but who cares? }} */
  605.         while (cmd_erase() == 0)
  606.             ;
  607.     } else
  608.     {
  609.         /*
  610.          * Append the character to the string,
  611.          * if there is room in the buffer and on the screen.
  612.          */
  613.         if (cp < &cmdbuf[sizeof(cmdbuf)-1] && cmd_col < sc_width-3)
  614.         {
  615.             *cp++ = c;
  616.             if (control_char(c))
  617.             {
  618.                 putc('^');
  619.                 cmd_col++;
  620.                 c = carat_char(c);
  621.             }
  622.             putc(c);
  623.             cmd_col++;
  624.         } else
  625.             bell();
  626.     }
  627.     return (0);
  628. }
  629.  
  630. /*
  631.  * Return the number currently in the command buffer.
  632.  */
  633.     static int
  634. cmd_int()
  635. {
  636.     *cp = '\0';
  637.     cp = cmdbuf;
  638.     return (atoi(cmdbuf));
  639. }
  640.  
  641. /*
  642.  * Move the cursor to lower left before executing a command.
  643.  * This looks nicer if the command takes a long time before
  644.  * updating the screen.
  645.  */
  646.     static void
  647. cmd_exec()
  648. {
  649.     lower_left();
  650.     flush();
  651. }
  652.  
  653. /*
  654.  * Display the appropriate prompt.
  655.  */
  656.     static void
  657. prompt()
  658. {
  659.     register char *p;
  660.  
  661.     if (first_cmd != NULL && *first_cmd != '\0')
  662.         /*
  663.          * No prompt necessary if commands are from first_cmd
  664.          * rather than from the user.
  665.          */
  666.         return;
  667.  
  668.     /*
  669.      * Select the proper prompt and display it.
  670.      */
  671.     p = pr_string();
  672.     if (p == NULL)
  673.         putc(':');
  674.     else
  675.     {
  676.         so_enter();
  677.         puts(p);
  678.         so_exit();
  679.     }
  680. }
  681.  
  682. /*
  683.  * Get command character.
  684.  * The character normally comes from the keyboard,
  685.  * but may come from the "first_cmd" string.
  686.  */
  687.     static int
  688. getcc()
  689. {
  690.     if (first_cmd == NULL)
  691.         return (getc());
  692.  
  693.     if (*first_cmd == '\0')
  694.     {
  695.         /*
  696.          * Reached end of first_cmd input.
  697.          */
  698.         first_cmd = NULL;
  699.         if (cp > cmdbuf && position(TOP) == NULL_POSITION)
  700.         {
  701.             /*
  702.              * Command is incomplete, so try to complete it.
  703.              * There are only two cases:
  704.              * 1. We have "/string" but no newline.  Add the \n.
  705.              * 2. We have a number but no command.  Treat as #g.
  706.              * (This is all pretty hokey.)
  707.              */
  708.             if (mcc != ':')
  709.                 return ('\n'); 
  710.             else
  711.                 return ('g');
  712.         }
  713.         return (getc());
  714.     }
  715.     return (*first_cmd++);
  716. }
  717.  
  718. /*
  719.  * Main command processor.
  720.  * Accept and execute commands until a quit command, then return.
  721.  */
  722.     public void
  723. commands()
  724. {
  725.     register int c;
  726.     register int n;
  727.     register int scroll = 10;
  728.  
  729.     mcc = last_mcc = 0;
  730.  
  731.     setjmp(main_loop);
  732.     for (;;)
  733.     {
  734.         /*
  735.          * Display prompt and accept a character.
  736.          */
  737.         psignals();    /* See if any signals need processing */
  738.  
  739.         if (quit_at_eof && hit_eof > 1)
  740.             /*
  741.              * After hitting end-of-file for the second time,
  742.              * automatically advance to the next file.
  743.              * If there are no more files, quit.
  744.              */
  745.             next_file(1);
  746.  
  747.         cmd_reset();
  748.         lower_left();
  749.         clear_eol();
  750.         prompt();
  751.         c = getcc();
  752.  
  753.     again:
  754.         if (sigs)
  755.             continue;
  756.  
  757.         if (mcc)
  758.         {
  759.             /*
  760.              * We are in a multi-character command.  
  761.              * All chars until newline go into the command buffer.
  762.              * (Note that mcc == ':' is a special case that
  763.              *  means a number is being entered.)
  764.              */
  765.             if (mcc != ':' && (c == '\n' || c == '\r'))
  766.             {
  767.                 /*
  768.                  * Execute the command.
  769.                  */
  770.                 *cp = '\0';
  771.                 cmd_exec();
  772.                 if (mcc == 'E')
  773.                 {
  774.                     char *p;
  775.                     /*
  776.                      * Ignore leading spaces 
  777.                      * in the filename.
  778.                      */
  779.                     for (p = cmdbuf;  *p == ' ';  p++) ;
  780.                     edit(p);
  781. #if SHELL_ESCAPE
  782.                 } else if (mcc == '!')
  783.                 {
  784.                     lsystem(cmdbuf);
  785.                     error("!done");
  786.                     first_cmd = "r";    /* Repaint */
  787. #endif
  788.                 } else
  789.                     search(mcc, cmdbuf, n);
  790.                 mcc = 0;
  791.             } else
  792.             {
  793.                 if (mcc == ':' && (c < '0' || c > '9') &&
  794.                     c != erase_char && c != kill_char)
  795.                 {
  796.                     /*
  797.                      * This is not part of the number
  798.                      * we were entering.  Process
  799.                      * it as a regular character.
  800.                      */
  801.                     mcc = 0;
  802.                     goto again;
  803.                 }
  804.  
  805.                 /*
  806.                  * Append the char to the command buffer.
  807.                  */
  808.                 if (cmd_char(c))
  809.                 {
  810.                     /* Abort the multi-char command. */
  811.                     mcc = 0;
  812.                     continue;
  813.                 }
  814.                 c = getcc();
  815.                 goto again;
  816.             }
  817.         } else switch (c)
  818.         {
  819.         case '0': case '1': case '2': case '3': case '4':
  820.         case '5': case '6': case '7': case '8': case '9':
  821.             /*
  822.              * First digit of a number.
  823.              */
  824.             mcc = ':';
  825.             start_mcc();
  826.             goto again;
  827.  
  828.         case 'f':
  829.         case ' ':
  830.         case CONTROL('F'):
  831.             /*
  832.              * Forward one screen.
  833.              */
  834.             n = cmd_int();
  835.             if (n <= 0)
  836.                 n = sc_window;
  837.             forward(n, 1);
  838.             break;
  839.  
  840.         case 'b':
  841.         case CONTROL('B'):
  842.             /*
  843.              * Backward one screen.
  844.              */
  845.             n = cmd_int();
  846.             if (n <= 0)
  847.                 n = sc_window;
  848.             backward(n, 1);
  849.             break;
  850.  
  851.         case 'e':
  852.         case 'j':
  853.         case '\r':
  854.         case '\n':
  855.         case CONTROL('E'):
  856.             /*
  857.              * Forward N (default 1) line.
  858.              */
  859.             n = cmd_int();
  860.             if (n <= 0)
  861.                 n = 1;
  862.             forward(n, 0);
  863.             break;
  864.  
  865.         case 'y':
  866.         case 'k':
  867.         case CONTROL('K'):
  868.         case CONTROL('Y'):
  869.             /*
  870.              * Backward N (default 1) line.
  871.              */
  872.             n = cmd_int();
  873.             if (n <= 0)
  874.                 n = 1;
  875.             backward(n, 0);
  876.             break;
  877.  
  878.         case 'd':
  879.         case CONTROL('D'):
  880.             /*
  881.              * Forward N lines 
  882.              * (default same as last 'd' or 'u' command).
  883.              */
  884.             n = cmd_int();
  885.             if (n > 0)
  886.                 scroll = n;
  887.             forward(scroll, 0);
  888.             break;
  889.  
  890.         case 'u':
  891.         case CONTROL('U'):
  892.             /*
  893.              * Forward N lines 
  894.              * (default same as last 'd' or 'u' command).
  895.              */
  896.             n = cmd_int();
  897.             if (n > 0)
  898.                 scroll = n;
  899.             backward(scroll, 0);
  900.             break;
  901.  
  902.         case 'R':
  903.             /*
  904.              * Flush buffers, then repaint screen.
  905.              */
  906.             ch_init(0);
  907.             /* Fall thru */
  908.         case 'r':
  909.         case CONTROL('R'):
  910.         case CONTROL('L'):
  911.             /*
  912.              * Repaint screen.
  913.              */
  914.             repaint();
  915.             break;
  916.  
  917.         case 'g':
  918.             /*
  919.              * Go to line N, default beginning of file.
  920.              */
  921.             n = cmd_int();
  922.             if (n <= 0)
  923.                 n = 1;
  924.             cmd_exec();
  925.             jump_back(n);
  926.             break;
  927.  
  928.         case 'p':
  929.         case '%':
  930.             /*
  931.              * Go to a specified percentage into the file.
  932.              */
  933.             n = cmd_int();
  934.             if (n < 0)
  935.                 n = 0;
  936.             if (n > 100)
  937.                 n = 100;
  938.             cmd_exec();
  939.             jump_percent(n);
  940.             break;
  941.  
  942.         case 'G':
  943.             /*
  944.              * Go to line N, default end of file.
  945.              */
  946.             n = cmd_int();
  947.             cmd_exec();
  948.             if (n <= 0)
  949.                 jump_forw();
  950.             else
  951.                 jump_back(n);
  952.             break;
  953.  
  954.         case '=':
  955.         case CONTROL('G'):
  956.             /*
  957.              * Print file name, etc.
  958.              */
  959.             error(eq_message());
  960.             break;
  961.             
  962.         case 'V':
  963.             /*
  964.              * Print version number, without the "@(#)".
  965.              */
  966.             error(version+4);
  967.             break;
  968.  
  969.         case 'q':
  970.             /*
  971.              * Exit.
  972.              */
  973.             return;
  974.  
  975.         case '/':
  976.         case '?':
  977.             /*
  978.              * Search for a pattern.
  979.              * Accept chars of the pattern until \n.
  980.              */
  981.             n = cmd_int();
  982.             if (n <= 0)
  983.                 n = 1;
  984.             mcc = last_mcc = c;
  985.             start_mcc();
  986.             c = getcc();
  987.             goto again;
  988.  
  989.         case 'n':
  990.             /*
  991.              * Repeat previous search.
  992.              */
  993.             n = cmd_int();
  994.             if (n <= 0)
  995.                 n = 1;
  996.             mcc = last_mcc;
  997.             start_mcc();
  998.             cmd_exec();
  999.             search(mcc, (char *)NULL, n);
  1000.             mcc = 0;
  1001.             break;
  1002.  
  1003.         case 'h':
  1004.             /*
  1005.              * Help.
  1006.              */
  1007.             help();
  1008.             repaint();
  1009.             break;
  1010.  
  1011.         case 'E':
  1012.             /*
  1013.              * Edit a new file.  Get the filename.
  1014.              */
  1015.             cmd_reset();
  1016.             mcc = 'E';
  1017.             start_mcc();
  1018.             puts("dit: ");    /* This looks nicer */
  1019.             cmd_col += 5;
  1020.             c = getcc();
  1021.             goto again;
  1022.             
  1023. #if SHELL_ESCAPE
  1024.         case '!':
  1025.             /*
  1026.              * Shell escape.
  1027.              */
  1028.             cmd_reset();
  1029.             mcc = '!';
  1030.             start_mcc();
  1031.             c = getcc();
  1032.             goto again;
  1033. #endif
  1034.  
  1035. #if EDITOR
  1036.         case 'v':
  1037.             if (ispipe)
  1038.             {
  1039.                 error("Cannot edit standard input");
  1040.                 break;
  1041.             }
  1042.             sprintf(cmdbuf, "%s %s", editor, current_file);
  1043.             lsystem(cmdbuf);
  1044.             first_cmd = "R";
  1045.             break;
  1046. #endif
  1047.  
  1048.         case 'N':
  1049.             /*
  1050.              * Examine next file.
  1051.              */
  1052.             n = cmd_int();
  1053.             if (n <= 0)
  1054.                 n = 1;
  1055.             next_file(n);
  1056.             break;
  1057.  
  1058.         case 'P':
  1059.             /*
  1060.              * Examine previous file.
  1061.              */
  1062.             n = cmd_int();
  1063.             if (n <= 0)
  1064.                 n = 1;
  1065.             prev_file(n);
  1066.             break;
  1067.  
  1068.         case '-':
  1069.             /*
  1070.              * Toggle a flag setting.
  1071.              */
  1072.             mcc = '-';
  1073.             start_mcc();
  1074.             c = getcc();
  1075.             mcc = 0;
  1076.             if (c == erase_char || c == kill_char)
  1077.                 break;
  1078.             toggle_option(c);
  1079.             break;
  1080.  
  1081.         case 'm':
  1082.             /*
  1083.              * Set a mark.
  1084.              */
  1085.             lower_left();
  1086.             clear_eol();
  1087.             puts("mark: ");
  1088.             c = getcc();
  1089.             if (c == erase_char || c == kill_char)
  1090.                 break;
  1091.             setmark(c);
  1092.             break;
  1093.  
  1094.         case '\'':
  1095.             /*
  1096.              * Go to a mark.
  1097.              */
  1098.             lower_left();
  1099.             clear_eol();
  1100.             puts("goto mark: ");
  1101.             c = getcc();
  1102.             if (c == erase_char || c == kill_char)
  1103.                 break;
  1104.             gomark(c);
  1105.             break;
  1106.  
  1107.         default:
  1108.             bell();
  1109.             break;
  1110.         }
  1111.     }
  1112. }
  1113. SHAR_EOF
  1114. fi
  1115. if test -f 'funcs.h'
  1116. then
  1117.     echo shar: "will not over-write existing file 'funcs.h'"
  1118. else
  1119. cat << \SHAR_EOF > 'funcs.h'
  1120.     public void edit ();
  1121.     public void next_file ();
  1122.     public void prev_file ();
  1123.     public void quit ();
  1124.     public void init_option ();
  1125.     public void toggle_option ();
  1126.     public void scan_option ();
  1127.     public void forward ();
  1128.     public void backward ();
  1129.     public void repaint ();
  1130.     public void jump_forw ();
  1131.     public void jump_back ();
  1132.     public void jump_percent ();
  1133.     public void jump_loc ();
  1134.     public void init_mark ();
  1135.     public void setmark ();
  1136.     public void gomark ();
  1137.     public void search ();
  1138.     public int ch_seek ();
  1139.     public int ch_end_seek ();
  1140.     public POSITION ch_length ();
  1141.     public POSITION ch_tell ();
  1142.     public int ch_forw_get ();
  1143.     public int ch_back_get ();
  1144.     public void ch_init ();
  1145.     public POSITION position ();
  1146.     public void add_forw_pos ();
  1147.     public void add_back_pos ();
  1148.     public void pos_clear ();
  1149.     public int onscreen ();
  1150.     public POSITION forw_line ();
  1151.     public POSITION back_line ();
  1152.     public void put_line ();
  1153.     public int control_char ();
  1154.     public int carat_char ();
  1155.     public void flush ();
  1156.     public void dropout ();
  1157.     public void putc ();
  1158.     public void puts ();
  1159.     public void error ();
  1160.     public int error_width ();
  1161.     public void raw_mode ();
  1162.     public void get_term ();
  1163.     public void init ();
  1164.     public void deinit ();
  1165.     public void home ();
  1166.     public void add_line ();
  1167.     public void lower_left ();
  1168.     public void bell ();
  1169.     public void vbell ();
  1170.     public void clear ();
  1171.     public void clear_eol ();
  1172.     public void so_enter ();
  1173.     public void so_exit ();
  1174.     public void ul_enter ();
  1175.     public void ul_exit ();
  1176.     public void backspace ();
  1177.     public void putbs ();
  1178.     public char * eq_message ();
  1179.     public char * pr_string ();
  1180.     public void prewind ();
  1181.     public int pappend ();
  1182.     public POSITION forw_raw_line ();
  1183.     public POSITION back_raw_line ();
  1184.     public void init_signals ();
  1185.     public void  psignals ();
  1186.     public void lsystem ();
  1187.     public void help ();
  1188.     public void open_getc ();
  1189.     public int getc ();
  1190.     public void commands ();
  1191. SHAR_EOF
  1192. fi
  1193. if test -f 'help.c'
  1194. then
  1195.     echo shar: "will not over-write existing file 'help.c'"
  1196. else
  1197. cat << \SHAR_EOF > 'help.c'
  1198. #include  "less.h"
  1199.  
  1200. /*
  1201.  * Display some help.
  1202.  * Help is in two pages.
  1203.  */
  1204.     static void
  1205. help0()
  1206. {
  1207.     puts("f, SPACE       Forward one screen.\n");
  1208.     puts("b              Backward one screen.\n");
  1209.     puts("e, j, CR    *  Forward N lines, default 1.\n");
  1210.     puts("y, k        *  Backward N lines, default 1.\n");
  1211.     puts("d           *  Forward N lines, default 10 or last N to d or u command.\n");
  1212.     puts("u           *  Backward N lines, default 10 or last N to d or u command.\n");
  1213.     puts("r              Repaint screen.\n");
  1214.     puts("g           *  Go to line N, default 1.\n");
  1215.     puts("G           *  Like g, but default is last line in file.\n");
  1216.     puts("=              Print current file name\n");
  1217.     puts("/pattern    *  Search forward for N-th occurence of pattern.\n");
  1218.     puts("?pattern    *  Search backward for N-th occurence of pattern.\n");
  1219.     puts("n           *  Repeat previous search (for N-th occurence).\n");
  1220.     puts("q              Exit.\n");
  1221.     error("More help...");
  1222. }
  1223.  
  1224.     static void
  1225. help1()
  1226. {
  1227.     char message[100];
  1228.     extern char all_options[];
  1229.  
  1230.     puts("R              Repaint screen, discarding buffered input.\n");
  1231.     puts("p, %        *  Position to N percent into the file.\n");
  1232.     puts("m<letter>      Mark the current position with <letter>.\n");
  1233.     puts("'<letter>      Return to a previously marked position.\n");
  1234.     sprintf(message, 
  1235.          "-X             Toggle a flag (X may be one of \"%s\").\n", 
  1236.                 all_options);
  1237.     puts(message);
  1238.     puts("E [file]       Examine a new file.\n");
  1239.     puts("N              Examine the next file (from the command line).\n");
  1240.     puts("P              Examine the previous file (from the command line).\n");
  1241.     puts("V              Print version number.\n");
  1242. #if SHELL_ESCAPE
  1243.     puts("!command       Passes the command to a shell to be executed.\n");
  1244. #endif
  1245. #if EDITOR
  1246.     sprintf(message,
  1247.          "v              Edit the current file with $EDITOR (default %s).\n",
  1248.                 EDIT_PGM);
  1249.     puts(message);
  1250. #endif
  1251.     error("");
  1252. }
  1253.  
  1254.     public void
  1255. help()
  1256. {
  1257.     register int i;
  1258.  
  1259.     for (i = 0;  i < 2;  i++)
  1260.     {
  1261.         clear();
  1262.         puts("Commands marked with * may be preceeded by a number, N.\n\n");
  1263.  
  1264.         switch (i)
  1265.         {
  1266.         case 0:        help0();    break;
  1267.         case 1:        help1();    break;
  1268.         }
  1269.     }
  1270. }
  1271. SHAR_EOF
  1272. fi
  1273. if test -f 'input.c'
  1274. then
  1275.     echo shar: "will not over-write existing file 'input.c'"
  1276. else
  1277. cat << \SHAR_EOF > 'input.c'
  1278. /*
  1279.  * High level routines dealing with getting lines of input 
  1280.  * from the file being viewed.
  1281.  *
  1282.  * When we speak of "lines" here, we mean PRINTABLE lines;
  1283.  * lines processed with respect to the screen width.
  1284.  * We use the term "raw line" to refer to lines simply
  1285.  * delimited by newlines; not processed with respect to screen width.
  1286.  */
  1287.  
  1288. #include "less.h"
  1289.  
  1290. extern int do_bs;
  1291. extern int squeeze;
  1292. extern char *line;
  1293.  
  1294. /*
  1295.  * Get the next line.
  1296.  * A "current" position is passed and a "new" position is returned.
  1297.  * The current position is the position of the first character of
  1298.  * a line.  The new position is the position of the first character
  1299.  * of the NEXT line.  The line obtained is the line starting at curr_pos.
  1300.  */
  1301.     public POSITION
  1302. forw_line(curr_pos)
  1303.     POSITION curr_pos;
  1304. {
  1305.     POSITION new_pos;
  1306.     register int c;
  1307.  
  1308.     if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
  1309.         return (NULL_POSITION);
  1310.  
  1311.     c = ch_forw_get();
  1312.     if (c == EOF)
  1313.         return (NULL_POSITION);
  1314.  
  1315.     prewind();
  1316.     for (;;)
  1317.     {
  1318.         if (c == '\n' || c == EOF)
  1319.         {
  1320.             /*
  1321.              * End of the line.
  1322.              */
  1323.             new_pos = ch_tell();
  1324.             break;
  1325.         }
  1326.  
  1327.         /*
  1328.          * Append the char to the line and get the next char.
  1329.          */
  1330.         if (pappend(c))
  1331.         {
  1332.             /*
  1333.              * The char won't fit in the line; the line
  1334.              * is too long to print in the screen width.
  1335.              * End the line here.
  1336.              */
  1337.             new_pos = ch_tell() - 1;
  1338.             break;
  1339.         }
  1340.         c = ch_forw_get();
  1341.     }
  1342.     (void) pappend('\0');
  1343.  
  1344.     if (squeeze && *line == '\0')
  1345.     {
  1346.         /*
  1347.          * This line is blank.
  1348.          * Skip down to the last contiguous blank line
  1349.          * and pretend it is the one which we are returning.
  1350.          */
  1351.         while ((c = ch_forw_get()) == '\n')
  1352.             ;
  1353.         if (c != EOF)
  1354.             (void) ch_back_get();
  1355.         new_pos = ch_tell();
  1356.     }
  1357.  
  1358.     return (new_pos);
  1359. }
  1360.  
  1361. /*
  1362.  * Get the previous line.
  1363.  * A "current" position is passed and a "new" position is returned.
  1364.  * The current position is the position of the first character of
  1365.  * a line.  The new position is the position of the first character
  1366.  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
  1367.  */
  1368.     public POSITION
  1369. back_line(curr_pos)
  1370.     POSITION curr_pos;
  1371. {
  1372.     POSITION new_pos, begin_new_pos;
  1373.     int c;
  1374.  
  1375.     if (curr_pos == NULL_POSITION || curr_pos <= (POSITION)0 ||
  1376.         ch_seek(curr_pos-1))
  1377.         return (NULL_POSITION);
  1378.  
  1379.     if (squeeze)
  1380.     {
  1381.         /*
  1382.          * Find out if the "current" line was blank.
  1383.          */
  1384.         (void) ch_forw_get();    /* Skip the newline */
  1385.         c = ch_forw_get();    /* First char of "current" line */
  1386.         (void) ch_back_get();    /* Restore our position */
  1387.         (void) ch_back_get();
  1388.  
  1389.         if (c == '\n')
  1390.         {
  1391.             /*
  1392.              * The "current" line was blank.
  1393.              * Skip over any preceeding blank lines,
  1394.              * since we skipped them in forw_line().
  1395.              */
  1396.             while ((c = ch_back_get()) == '\n')
  1397.                 ;
  1398.             if (c == EOF)
  1399.                 return (NULL_POSITION);
  1400.             (void) ch_forw_get();
  1401.         }
  1402.     }
  1403.  
  1404.     /*
  1405.      * Scan backwards until we hit the beginning of the line.
  1406.      */
  1407.     for (;;)
  1408.     {
  1409.         c = ch_back_get();
  1410.         if (c == '\n')
  1411.         {
  1412.             /*
  1413.              * This is the newline ending the previous line.
  1414.              * We have hit the beginning of the line.
  1415.              */
  1416.             new_pos = ch_tell() + 1;
  1417.             break;
  1418.         }
  1419.         if (c == EOF)
  1420.         {
  1421.             /*
  1422.              * We have hit the beginning of the file.
  1423.              * This must be the first line in the file.
  1424.              * This must, of course, be the beginning of the line.
  1425.              */
  1426.             new_pos = (POSITION)0;
  1427.             break;
  1428.         }
  1429.     }
  1430.  
  1431.     /*
  1432.      * Now scan forwards from the beginning of this line.
  1433.      * We keep discarding "printable lines" (based on screen width)
  1434.      * until we reach the curr_pos.
  1435.      *
  1436.      * {{ This algorithm is pretty inefficient if the lines
  1437.      *    are much longer than the screen width, 
  1438.      *    but I don't know of any better way. }}
  1439.      */
  1440.     if (ch_seek(new_pos))
  1441.         return (NULL_POSITION);
  1442.     loop:
  1443.     begin_new_pos = new_pos;
  1444.     prewind();
  1445.  
  1446.     do
  1447.     {
  1448.         c = ch_forw_get();
  1449.         new_pos++;
  1450.         if (c == '\n')
  1451.             break;
  1452.         if (pappend(c))
  1453.         {
  1454.             /*
  1455.              * Got a full printable line, but we haven't
  1456.              * reached our curr_pos yet.  Discard the line
  1457.              * and start a new one.
  1458.              */
  1459.             (void) pappend('\0');
  1460.             (void) ch_back_get();
  1461.             new_pos--;
  1462.             goto loop;
  1463.         }
  1464.     } while (new_pos < curr_pos);
  1465.  
  1466.     (void) pappend('\0');
  1467.  
  1468.     return (begin_new_pos);
  1469. }
  1470. SHAR_EOF
  1471. fi
  1472. if test -f 'less.h'
  1473. then
  1474.     echo shar: "will not over-write existing file 'less.h'"
  1475. else
  1476. cat << \SHAR_EOF > 'less.h'
  1477. /*
  1478.  * Standard include file for "less".
  1479.  */
  1480.  
  1481. /*
  1482.  * Language details.
  1483.  */
  1484. #if !VOID
  1485. #define    void  int
  1486. #endif
  1487. #define    public        /* PUBLIC FUNCTION */
  1488.  
  1489. /*
  1490.  * Special types and constants.
  1491.  */
  1492. typedef long        POSITION;
  1493. /*
  1494.  * {{ Warning: if POSITION is changed to other than "long",
  1495.  *    you may have to change some of the printfs which use "%ld"
  1496.  *    to print a variable of type POSITION. }}
  1497.  */
  1498.  
  1499. #define    END_POSITION    ((POSITION)(-2))
  1500. #define    NULL_POSITION    ((POSITION)(-1))
  1501.  
  1502. #define    EOF        (0)
  1503. #define    NULL        (0)
  1504.  
  1505. /* How quiet should we be? */
  1506. #define    NOT_QUIET    0    /* Ring bell at eof and for errors */
  1507. #define    LITTLE_QUIET    1    /* Ring bell only for errors */
  1508. #define    VERY_QUIET    2    /* Never ring bell */
  1509.  
  1510. /* How should we prompt? */
  1511. #define    PR_SHORT    0    /* Prompt with colon */
  1512. #define    PR_MEDIUM    1    /* Prompt with message */
  1513. #define    PR_LONG        2    /* Prompt with longer message */
  1514.  
  1515. /* How should we handle backspaces? */
  1516. #define    BS_SPECIAL    0    /* Do special things for underlining and bold */
  1517. #define    BS_NORMAL    1    /* \b treated as normal char; actually output */
  1518. #define    BS_CONTROL    2    /* \b treated as control char; prints as ^H */
  1519.  
  1520. /* Flag to eq_message() telling what to put in the message */
  1521. #define    MNAME        001    /* File name */
  1522. #define    MOF        002    /* "file x of y" */
  1523. #define    MBYTE        004    /* "byte x/y" */
  1524. #define    MPCT        010    /* Percentage into the file */
  1525.  
  1526. /* Special chars used to tell put_line() to do something special */
  1527. #define    UL_CHAR        '\201'    /* Enter underline mode */
  1528. #define    UE_CHAR        '\202'    /* Exit underline mode */
  1529. #define    BO_CHAR        '\203'    /* Enter boldface mode */
  1530. #define    BE_CHAR        '\204'    /* Exit boldface mode */
  1531.  
  1532. #define    CONTROL(c)        ((c)&037)
  1533. #define    SIGNAL(sig,func)    signal(sig,func)
  1534.  
  1535. off_t lseek();
  1536.  
  1537. #include "funcs.h"
  1538. SHAR_EOF
  1539. fi
  1540. if test -f 'less.l'
  1541. then
  1542.     echo shar: "will not over-write existing file 'less.l'"
  1543. else
  1544. cat << \SHAR_EOF > 'less.l'
  1545. .TH LESS l
  1546. .SH NAME
  1547. less \- opposite of more
  1548. .SH SYNOPSIS
  1549. .B "less [\-cdepstwmMqQuU] [\-h\fIn\fB] [\-b[fp]\fIn\fB] [\-x\fIn\fB] [\-[z]\fIn\fB] [+\fIcmd\fB] [\fIname\fB] ..."
  1550. .SH DESCRIPTION
  1551. \fILess\fR is a program similar to \fImore\fR(1), but which allows backwards
  1552. movement in the file as well as forward movement.  Also, \fIless\fR does not
  1553. have to read the entire input file before starting, so with large input
  1554. files it starts up faster than text editors like \fIvi\fR(1).  \fILess\fR
  1555. uses termcap, so it can run on a variety of terminals.  There is even
  1556. limited support for hardcopy terminals.  (On a hardcopy terminal, lines
  1557. which should be printed at the top of the screen are prefixed with an
  1558. up-arrow.)
  1559. .PP
  1560. Commands are based on both \fImore\fR and \fIvi\fR.  Commands may be
  1561. preceeded by a decimal number, called N in the descriptions below.  The
  1562. number is used by some commands, as indicated.
  1563. .SH COMMANDS
  1564. .IP \fBh\fR
  1565. Help: display a summary of these commands.  If you forget all the other
  1566. commands, remember this one.
  1567. .PP
  1568. .IP \fBSPACE\fR
  1569. Scroll forward N lines, default one window (see option \fB\-z\fR below).  If
  1570. N is more than the screen size, only one screenful is displayed.
  1571. .PP
  1572. .IP \fBf\fR
  1573. Same as \fBSPACE\fR.
  1574. .PP
  1575. .IP \fBb\fR
  1576. Scroll backward N lines, default one window (see option \fB\-z\fR below).
  1577. If N is more than the screen size, only one screenful is displayed.
  1578. .PP
  1579. .IP \fBRETURN\fR
  1580. Scroll forward N lines, default 1.  If N is more than the screen size, the
  1581. entire N lines are displayed.
  1582. .PP
  1583. .IP \fBe\fR
  1584. Same as \fBRETURN\fR.
  1585. .PP
  1586. .IP \fBj\fR
  1587. Also the same as \fBRETURN\fR.
  1588. .PP
  1589. .IP \fBy\fR
  1590. Scroll backward N lines, default 1.  If N is more than the screen size, the
  1591. entire N lines are displayed.
  1592. .IP \fBk\fR
  1593. Same as \fBy\fR.
  1594. .PP
  1595. .IP \fBd\fR
  1596. Scroll forward N lines, default 10.  If N is specified, it becomes the new
  1597. default for all \fBd\fR and \fBu\fR commands.
  1598. .PP
  1599. .IP \fBu\fR
  1600. Scroll backward N lines, default 10.  If N is specified, it becomes the new
  1601. default for all \fBd\fR and \fBu\fR commands.
  1602. .PP
  1603. .IP \fBr\fR
  1604. Repaint the screen.
  1605. .PP
  1606. .IP \fBR\fR
  1607. Repaint the screen, discarding any buffered input.  Useful if the file is
  1608. changing while it is being viewed.
  1609. .PP
  1610. .IP \fBg\fR
  1611. Go to line N in the file, default 1 (beginning of file).  (Warning: this may
  1612. be slow if N is large.)
  1613. .PP
  1614. .IP \fBG\fR
  1615. Go to line N in the file, default the end of the file.  (Warning: this may
  1616. be slow if standard input, rather than a file, is being read.)
  1617. .PP
  1618. .IP \fBp\fR
  1619. Go to a position N percent into the file.  N should be between 0 and 100.
  1620. (This is possible if standard input is being read, but only if \fIless\fR
  1621. has already read to the end of the file.  It is always fast, but not always
  1622. useful.)
  1623. .PP
  1624. .IP \fB%\fR
  1625. Same as \fBp\fR.
  1626. .PP
  1627. .IP \fBm\fIl\fR
  1628. Followed by any lowercase letter, \fIl\fR, marks the current position with
  1629. that letter.
  1630. .PP
  1631. .IP \fB'\fIl\fR
  1632. Followed by any lowercase letter, \fIl\fR, returns to the position which was
  1633. previously marked with that letter.  All marks are lost when a new file is
  1634. examined.
  1635. .PP
  1636. .IP \fB/pattern\fR
  1637. Search forward in the file for the N-th occurence of the \fIpattern\fR.  N
  1638. defaults to 1.  The \fIpattern\fR is a regular expression, as recognized by
  1639. \fIed\fR.  The search starts at the second line displayed (but see the
  1640. \fB\-t\fR option, which changes this).
  1641. .PP
  1642. .IP \fB?pattern\fR
  1643. Search backward in the file for the N-th occurence of the \fIpattern\fR.
  1644. The search starts at the line immediately before the top line displayed.
  1645. .PP
  1646. .IP \fBn\fR
  1647. Repeat previous search, for N-th occurence of the last \fIpattern\fR.
  1648. .PP
  1649. .IP \fBE\fR\ \fI[filename]\fR
  1650. Examine a new file.  If the \fIfilename\fR is missing, the "current" file
  1651. (see the \fBN\fR and \fBP\fR commands below) from the list of files in the
  1652. command line is re-examined.
  1653. .PP
  1654. .IP \fBN\fR
  1655. Examine the next file (from the list of files given in the command line).
  1656. If a number N is specified (not to be confused with the command \fBN\fR),
  1657. the N-th next file is examined.
  1658. .PP
  1659. .IP \fBP\fR
  1660. Examine the previous file.  If a number N is specified, the N-th previous
  1661. file is examined.
  1662. .PP
  1663. .IP \fB=\fR
  1664. Prints the name of the file being viewed and the byte offset of the bottom
  1665. line being displayed.  If possible, it also prints the length of the file
  1666. and the percent of the file above the last displayed line.
  1667. .PP
  1668. .IP \fB\-\fR
  1669. Followed by one of the command line option letters (see below), this will
  1670. toggle the setting of that option and print a message describing the new
  1671. setting.
  1672. .PP
  1673. .IP \fBV\fR
  1674. Prints the version number of \fIless\fR being run.
  1675. .PP
  1676. .IP \fBq\fR
  1677. Exits \fIless\fR.
  1678. .PP
  1679. The following two commands may or may not be valid, depending on your
  1680. particular installation.
  1681. .PP
  1682. .IP \fBv\fR
  1683. Invokes an editor to edit the current file being viewed.  The editor is
  1684. taken from the environment variable \fBEDITOR\fR, or defaults to \fIvi\fR.
  1685. .PP
  1686. .IP \fB!\fR\ \fIshell-command\fR
  1687. Invokes a shell to run the
  1688. .I shell-command
  1689. given.
  1690. .PP
  1691. .SH OPTIONS
  1692. Command line options are described below.  Options are also taken from the
  1693. environment variable \fBLESS\fR.  (The environment variable is parsed before
  1694. the command line, so command line options override the \fBLESS\fR environment
  1695. variable.  Options may be changed while \fIless\fR is running via the
  1696. \fB"\-"\fR command.)  For example, if you like more-style prompting, to
  1697. avoid typing \fBless\ \-m\ ...\fR each time \fIless\fR is invoked, you might
  1698. tell \fIcsh\fR:
  1699. .sp
  1700. .B setenv LESS m
  1701. .sp
  1702. or if you use \fIsh\fR:
  1703. .sp
  1704. .B LESS=m; export LESS
  1705. .IP \fB\-s\fR
  1706. The \fB\-s\fR flag causes consecutive blank lines to be squeezed into a
  1707. single blank line.  This is useful when viewing \fInroff\fR output.
  1708. .IP \fB\-t\fR
  1709. Normally, forward searches start just after the top displayed line (that is,
  1710. at the second displayed line).  Thus forward searches include the currently
  1711. displayed screen.  The \fB\-t\fR command line option causes forward searches
  1712. to start just after the bottom line displayed, thus skipping the currently
  1713. displayed screen.
  1714. .IP \fB\-m\fR
  1715. Normally, \fIless\fR prompts with a colon.  The \fB\-m\fR command line
  1716. option causes \fIless\fR to prompt verbosely like \fImore\fR, printing the
  1717. file name and percent into the file.
  1718. .IP \fB\-M\fR
  1719. The \fB\-M\fR command line option causes \fIless\fR to prompt even more
  1720. verbosely than \fImore\fR.
  1721. .IP \fB\-q\fR
  1722. Normally, if an attempt is made to scroll past the end of the file or before
  1723. the beginning of the file, the terminal bell is rung to indicate this fact.
  1724. The \fB\-q\fR command line option tells \fIless\fR not to ring the bell at
  1725. such times.  If the terminal has a "visual bell", it is used instead.
  1726. .IP \fB\-Q\fR
  1727. Even if \fB\-q\fR is given, \fIless\fR will ring the bell on certain other
  1728. errors, such as typing an invalid character.  The \fB\-Q\fR command line
  1729. option tells \fIless\fR to be quiet all the time; that is, never ring the
  1730. terminal bell.  If the terminal has a "visual bell", it is used instead.
  1731. .IP \fB\-e\fR
  1732. Normally the only way to exit less is via the "q" command.  The \fB\-e\fR
  1733. command line option tells less to automatically exit the second time it
  1734. reaches end-of-file.
  1735. .IP \fB\-u\fR
  1736. If the \fB\-u\fR command line option is given, backspaces are treated as
  1737. printable characters; that is, they are sent to the terminal when they
  1738. appear in the input.
  1739. .IP \fB\-U\fR
  1740. If the \fB\-U\fR command line option is given, backspaces are printed as the
  1741. two character sequence "^H".  If neither \fB\-u\fR nor \fB\-U\fR is given,
  1742. backspaces which appear adjacent to an underscore character or sequences of
  1743. a character interleaved with backspaces are treated specially:  the
  1744. underlined or boldfaced text is displayed using the terminal's hardware
  1745. capability.  Note that the \fB\-v\fR option below superceeds both \fB\-u\fR
  1746. and \fB\-U\fR.
  1747. .IP \fB\-w\fR
  1748. Normally, \fIless\fR uses a tilde character to represent lines past the end
  1749. of the file.  The \fB\-w\fR option causes blank lines to be used instead.
  1750. .IP \fB\-d\fR
  1751. Normally, \fIless\fR will complain if the terminal is dumb; that is, lacks
  1752. some important capability, such as the ability to clear the screen or scroll
  1753. backwards.  The \fB\-d\fR flag suppresses this complaint (but does not
  1754. otherwise change the behavior of the program on a dumb terminal).
  1755. .IP \fB\-p\fR
  1756. Normally, \fIless\fR will repaint the screen by scrolling from the bottom of
  1757. the screen.  If the \fB\-p\fR flag is set, when \fIless\fR needs to change
  1758. the entire display, it will clear the screen and paint from the top line
  1759. down.
  1760. .IP \fB\-h\fIn\fR
  1761. Normally, \fIless\fR will scroll backwards when backwards movement is
  1762. necessary.  The \fB\-h\fR option specifies a maximum number of lines to
  1763. scroll backwards.  If it is necessary to move backwards more than this many
  1764. lines, the screen is repainted in a forward direction.  (If the terminal
  1765. does not have the ability to scroll backwards, \fB\-h\fI0\fR is implied.)
  1766. .IP \fB\-[z]\fIn\fR
  1767. When given a backwards or forwards window command, \fIless\fR will by
  1768. default scroll backwards or forwards one screenful of lines.  The \fB\-z\fR
  1769. option changes the default scrolling window size to \fIn\fR lines.  If
  1770. \fIn\fR is greater than the screen size, the scrolling window size will be
  1771. set to one screenful.  Note that the \fBz\fR is optional for compatibility
  1772. with more.
  1773. .IP \fB\-x\fR
  1774. The \fB\-x\fR command line option sets tab stops every \fIn\fR positions.
  1775. The default for \fIn\fR is 8.
  1776. .IP \fB\-b[fp]\fIn\fR
  1777. The \fB\-b\fR command line option tells \fIless\fR to use a non-standard
  1778. buffer size.  There are two standard (default) buffer sizes, one is used
  1779. when a file is being read and the other when a pipe (standard input) is
  1780. being read.  The current defaults are 5 buffers for files and 12 for pipes.
  1781. (Buffers are 1024 bytes.)  The number \fIn\fR specifies a different number
  1782. of buffers to use.  The \fB\-b\fR may be followed by \fBf\fR, in which case
  1783. only the file default is changed, or by \fBp\fR in which case only the pipe
  1784. default is changed.  Otherwise, both are changed.
  1785. .IP \fB\-c\fR
  1786. Normally, when data is read by \fIless\fR, it is scanned to ensure that bit
  1787. 7 (the high order bit) is turned off in each byte read, and to ensure that
  1788. there are no null (zero) bytes in the data (null bytes are turned into "@"
  1789. characters).  If the data is known to be "clean", the \fB\-c\fR command line
  1790. option will tell \fIless\fR to skip this checking, causing an imperceptible
  1791. speed improvement.  (However, if the data is not "clean", unpredicatable
  1792. results may occur.)
  1793. .IP \fB\-v\fR
  1794. The \fB\-v\fR option tells less to print non-printing characters in a
  1795. visible way ala \fIcat\fR(1).  Control characters are printed as ^X (the
  1796. delete character (octal 0177) is printed as ^?).  Characters with the 0200
  1797. bit set are printed as M- followed by the character represented by the low
  1798. order seven bits.
  1799. .IP \fB+\fIcommand\fR
  1800. If a command line option begins with \fB+\fR, the remainder of that option
  1801. is taken to be an initial command to \fIless\fR.  For example, \fB+\fIG\fR
  1802. tells \fIless\fR to start at the end of the file rather than the beginning,
  1803. and \fB+\fI/xyz\fR tells it to start at the first occurence of \fIxyz\fR in
  1804. the file.  As a special case, \fB+\fI<number>\fR acts like
  1805. \fB+\fI<number>g\fR; that is, it starts the display at the specified line
  1806. number (however, see the caveat under the \fBg\fR command above).  If the
  1807. option starts with \fB++\fR, the initial command applies to every file being
  1808. viewed, not just the first one.
  1809. .SH BUGS
  1810. When used on standard input (rather than a file), you can move backwards
  1811. only a finite amount, corresponding to that portion of the file which is
  1812. still buffered.
  1813. SHAR_EOF
  1814. fi
  1815. if test -f 'line.c'
  1816. then
  1817.     echo shar: "will not over-write existing file 'line.c'"
  1818. else
  1819. cat << \SHAR_EOF > 'line.c'
  1820. /*
  1821.  * Routines to manipulate the "line buffer".
  1822.  * The line buffer holds a line of output as it is being built
  1823.  * in preparation for output to the screen.
  1824.  * We keep track of the PRINTABLE length of the line as it is being built.
  1825.  */
  1826.  
  1827. #include "less.h"
  1828.  
  1829. static char linebuf[1024];    /* Buffer which holds the current output line */
  1830. static char *curr;        /* Pointer into linebuf */
  1831. static int column;        /* Printable length, accounting for
  1832.                    backspaces, etc. */
  1833. /*
  1834.  * A ridiculously complex state machine takes care of backspaces 
  1835.  * when in BS_SPECIAL mode.  The complexity arises from the attempt
  1836.  * to deal with all cases, especially involving long lines with underlining,
  1837.  * boldfacing or whatever.  There are still some cases which will break it.
  1838.  *
  1839.  * There are four states:
  1840.  *    LN_NORMAL is the normal state (not in underline mode).
  1841.  *    LN_UNDERLINE means we are in underline mode.  We expect to get
  1842.  *        either a sequence like "_\bX" or "X\b_" to continue
  1843.  *        underline mode, or anything else to end underline mode.
  1844.  *    LN_BOLDFACE means we are in boldface mode.  We expect to get sequences
  1845.  *        like "X\bX\b...X\bX" to continue boldface mode, or anything
  1846.  *        else to end boldface mode.
  1847.  *    LN_UL_X means we are one character after LN_UNDERLINE
  1848.  *        (we have gotten the '_' in "_\bX" or the 'X' in "X\b_").
  1849.  *    LN_UL_XB means we are one character after LN_UL_X 
  1850.  *        (we have gotten the backspace in "_\bX" or "X\b_";
  1851.  *        we expect one more ordinary character, 
  1852.  *        which will put us back in state LN_UNDERLINE).
  1853.  *    LN_BO_X means we are one character after LN_BOLDFACE
  1854.  *        (we have gotten the 'X' in "X\bX").
  1855.  *    LN_BO_XB means we are one character after LN_BO_X
  1856.  *        (we have gotten the backspace in "X\bX";
  1857.  *        we expect one more 'X' which will put us back
  1858.  *        in LN_BOLDFACE).
  1859.  */
  1860. static int ln_state;        /* Currently in normal/underline/bold/etc mode? */
  1861. #define    LN_NORMAL    0    /* Not in underline, boldface or whatever mode */
  1862. #define    LN_UNDERLINE    1    /* In underline, need next char */
  1863. #define    LN_UL_X        2    /* In underline, got char, need \b */
  1864. #define    LN_UL_XB    3    /* In underline, got char & \b, need one more */
  1865. #define    LN_BOLDFACE    4    /* In boldface, need next char */
  1866. #define    LN_BO_X        5    /* In boldface, got char, need \b */
  1867. #define    LN_BO_XB    6    /* In boldface, got char & \b, need same char */
  1868.  
  1869. public char *line;        /* Pointer to the current line.
  1870.                    Usually points to linebuf. */
  1871.  
  1872. extern int bs_mode;
  1873. extern int tabstop;
  1874. extern int bo_width, be_width;
  1875. extern int ul_width, ue_width;
  1876. extern int sc_width, sc_height;
  1877.  
  1878. /*
  1879.  * Rewind the line buffer.
  1880.  */
  1881.     public void
  1882. prewind()
  1883. {
  1884.     line = curr = linebuf;
  1885.     ln_state = LN_NORMAL;
  1886.     column = 0;
  1887. }
  1888.  
  1889. /*
  1890.  * Append a character to the line buffer.
  1891.  * Expand tabs into spaces, handle underlining, boldfacing, etc.
  1892.  * Returns 0 if ok, 1 if couldn't fit in buffer.
  1893.  */
  1894.  
  1895. #define    NEW_COLUMN(newcol)    if ((newcol) + ((ln_state)?ue_width:0) > sc_width) \
  1896.                     return (1); else column = (newcol)
  1897.  
  1898.     public int
  1899. pappend(c)
  1900.     int c;
  1901. {
  1902.     if (c == '\0')
  1903.     {
  1904.         /*
  1905.          * Terminate any special modes, if necessary.
  1906.          * Append a '\0' to the end of the line.
  1907.          */
  1908.         switch (ln_state)
  1909.         {
  1910.         case LN_UL_X:
  1911.             curr[0] = curr[-1];
  1912.             curr[-1] = UE_CHAR;
  1913.             curr++;
  1914.             break;
  1915.         case LN_BO_X:
  1916.             curr[0] = curr[-1];
  1917.             curr[-1] = BE_CHAR;
  1918.             curr++;
  1919.             break;
  1920.         case LN_UL_XB:
  1921.         case LN_UNDERLINE:
  1922.             *curr++ = UE_CHAR;
  1923.             break;
  1924.         case LN_BO_XB:
  1925.         case LN_BOLDFACE:
  1926.             *curr++ = BE_CHAR;
  1927.             break;
  1928.         }
  1929.         ln_state = LN_NORMAL;
  1930.         *curr = '\0';
  1931.         return (0);
  1932.     }
  1933.  
  1934.     if (curr > linebuf + sizeof(linebuf) - 12)
  1935.         /*
  1936.          * Almost out of room in the line buffer.
  1937.          * Don't take any chances.
  1938.          * {{ Linebuf is supposed to be big enough that this
  1939.          *    will never happen, but may need to be made 
  1940.          *    bigger for wide screens or lots of backspaces. }}
  1941.          */
  1942.         return (1);
  1943.  
  1944.     if (bs_mode == BS_SPECIAL)
  1945.     {
  1946.         /*
  1947.          * Advance the state machine.
  1948.          */
  1949.         switch (ln_state)
  1950.         {
  1951.         case LN_NORMAL:
  1952.             if (curr <= linebuf + 1 || curr[-1] != '\b')
  1953.                 break;
  1954.  
  1955.             if (c == curr[-2])
  1956.                 goto enter_boldface;
  1957.             if (c == '_' || curr[-2] == '_')
  1958.                 goto enter_underline;
  1959.             curr -= 2;
  1960.             break;
  1961.  
  1962. enter_boldface:
  1963.             /*
  1964.              * We have "X\bX" (including the current char).
  1965.              * Switch into boldface mode.
  1966.              */
  1967.             if (column + bo_width + be_width + 1 >= sc_width)
  1968.                 /*
  1969.                  * Not enough room left on the screen to 
  1970.                  * enter and exit boldface mode.
  1971.                  */
  1972.                 return (1);
  1973.  
  1974.             if (bo_width > 0 && 
  1975.                 curr > linebuf + 2 && curr[-3] == ' ')
  1976.             {
  1977.                 /*
  1978.                  * Special case for magic cookie terminals:
  1979.                  * if the previous char was a space, replace 
  1980.                  * it with the "enter boldface" sequence.
  1981.                  */
  1982.                 curr[-3] = BO_CHAR;
  1983.                 column += bo_width-1;
  1984.             } else
  1985.             {
  1986.                 curr[-1] = curr[-2];
  1987.                 curr[-2] = BO_CHAR;
  1988.                 column += bo_width;
  1989.                 curr++;
  1990.             }
  1991.             goto ln_bo_xb_case;
  1992.  
  1993. enter_underline:
  1994.             /*
  1995.              * We have either "_\bX" or "X\b_" (including
  1996.              * the current char).  Switch into underline mode.
  1997.              */
  1998.             if (column + ul_width + ue_width + 1 >= sc_width)
  1999.                 /*
  2000.                  * Not enough room left on the screen to 
  2001.                  * enter and exit underline mode.
  2002.                  */
  2003.                 return (1);
  2004.  
  2005.             if (ul_width > 0 && 
  2006.                 curr > linebuf + 2 && curr[-3] == ' ')
  2007.             {
  2008.                 /*
  2009.                  * Special case for magic cookie terminals:
  2010.                  * if the previous char was a space, replace 
  2011.                  * it with the "enter underline" sequence.
  2012.                  */
  2013.                 curr[-3] = UL_CHAR;
  2014.                 column += ul_width-1;
  2015.             } else
  2016.             {
  2017.                 curr[-1] = curr[-2];
  2018.                 curr[-2] = UL_CHAR;
  2019.                 column += ul_width;
  2020.                 curr++;
  2021.             }
  2022.             goto ln_ul_xb_case;
  2023.             /*NOTREACHED*/
  2024.         case LN_UL_XB:
  2025.             /*
  2026.              * Termination of a sequence "_\bX" or "X\b_".
  2027.              */
  2028.             if (c != '_' && curr[-2] != '_' && c == curr[-2])
  2029.             {
  2030.                 /*
  2031.                  * We seem to have run on from underlining
  2032.                  * into boldfacing - this is a nasty fix, but
  2033.                  * until this whole routine is rewritten as a
  2034.                  * real DFA, ...  well ...
  2035.                  */
  2036.                 curr[0] = curr[-2];
  2037.                 curr[-2] = UE_CHAR;
  2038.                 curr[-1] = BO_CHAR;
  2039.                 curr += 2; /* char & non-existent backspace */
  2040.                 ln_state = LN_BO_XB;
  2041.                 goto ln_bo_xb_case;
  2042.             }
  2043. ln_ul_xb_case:
  2044.             if (c == '_')
  2045.                 c = curr[-2];
  2046.             curr -= 2;
  2047.             ln_state = LN_UNDERLINE;
  2048.             break;
  2049.         case LN_BO_XB:
  2050.             /*
  2051.              * Termination of a sequnce "X\bX".
  2052.              */
  2053.             if (c != curr[-2] && (c == '_' || curr[-2] == '_'))
  2054.             {
  2055.                 /*
  2056.                  * We seem to have run on from
  2057.                  * boldfacing into underlining.
  2058.                  */
  2059.                 curr[0] = curr[-2];
  2060.                 curr[-2] = BE_CHAR;
  2061.                 curr[-1] = UL_CHAR;
  2062.                 curr += 2; /* char & non-existent backspace */
  2063.                 ln_state = LN_UL_XB;
  2064.                 goto ln_ul_xb_case;
  2065.             }
  2066. ln_bo_xb_case:
  2067.             curr -= 2;
  2068.             ln_state = LN_BOLDFACE;
  2069.             break;
  2070.         case LN_UNDERLINE:
  2071.             if (column + ue_width + bo_width + 1 + be_width >= sc_width)
  2072.                 /*
  2073.                  * We have just barely enough room to 
  2074.                  * exit underline mode and handle a possible
  2075.                  * underline/boldface run on mixup.
  2076.                  */
  2077.                 return (1);
  2078.             ln_state = LN_UL_X;
  2079.             break;
  2080.         case LN_BOLDFACE:
  2081.             if (c == '\b')
  2082.             {
  2083.                 ln_state = LN_BO_XB;
  2084.                 break;
  2085.             }
  2086.             if (column + be_width + ul_width + 1 + ue_width >= sc_width)
  2087.                 /*
  2088.                  * We have just barely enough room to 
  2089.                  * exit underline mode and handle a possible
  2090.                  * underline/boldface run on mixup.
  2091.                  */
  2092.                 return (1);
  2093.             ln_state = LN_BO_X;
  2094.             break;
  2095.         case LN_UL_X:
  2096.             if (c == '\b')
  2097.                 ln_state = LN_UL_XB;
  2098.             else
  2099.             {
  2100.                 /*
  2101.                  * Exit underline mode.
  2102.                  * We have to shuffle the chars a bit
  2103.                  * to make this work.
  2104.                  */
  2105.                 curr[0] = curr[-1];
  2106.                 curr[-1] = UE_CHAR;
  2107.                 column += ue_width;
  2108.                 if (ue_width > 0 && curr[0] == ' ')
  2109.                     /*
  2110.                      * Another special case for magic
  2111.                      * cookie terminals: if the next
  2112.                      * char is a space, replace it
  2113.                      * with the "exit underline" sequence.
  2114.                      */
  2115.                     column--;
  2116.                 else
  2117.                     curr++;
  2118.                 ln_state = LN_NORMAL;
  2119.             } 
  2120.             break;
  2121.         case LN_BO_X:
  2122.             if (c == '\b')
  2123.                 ln_state = LN_BO_XB;
  2124.             else
  2125.             {
  2126.                 /*
  2127.                  * Exit boldface mode.
  2128.                  * We have to shuffle the chars a bit
  2129.                  * to make this work.
  2130.                  */
  2131.                 curr[0] = curr[-1];
  2132.                 curr[-1] = BE_CHAR;
  2133.                 column += be_width;
  2134.                 if (be_width > 0 && curr[0] == ' ')
  2135.                     /*
  2136.                      * Another special case for magic
  2137.                      * cookie terminals: if the next
  2138.                      * char is a space, replace it
  2139.                      * with the "exit boldface" sequence.
  2140.                      */
  2141.                     column--;
  2142.                 else
  2143.                     curr++;
  2144.                 ln_state = LN_NORMAL;
  2145.             } 
  2146.             break;
  2147.         }
  2148.     }
  2149.     
  2150.     if (c == '\t') 
  2151.     {
  2152.         /*
  2153.          * Expand a tab into spaces.
  2154.          */
  2155.         do
  2156.         {
  2157.             NEW_COLUMN(column+1);
  2158.         } while ((column % tabstop) != 0);
  2159.         *curr++ = '\t';
  2160.         return (0);
  2161.     }
  2162.  
  2163.     if (c == '\b')
  2164.     {
  2165.         if (bs_mode == BS_CONTROL)
  2166.         {
  2167.             /*
  2168.              * Treat backspace as a control char: output "^H".
  2169.              */
  2170.             NEW_COLUMN(column+2);
  2171.             *curr++ = ('H' | 0200);
  2172.         } else
  2173.         {
  2174.             /*
  2175.              * Output a real backspace.
  2176.              */
  2177.             column--;
  2178.             *curr++ = '\b';
  2179.         }
  2180.         return (0);
  2181.     } 
  2182.  
  2183.     if (control_char(c))
  2184.     {
  2185.         /*
  2186.          * Put a "^X" into the buffer.
  2187.          * The 0200 bit is used to tell put_line() to prefix
  2188.          * the char with a ^.  We don't actually put the ^
  2189.          * in the buffer because we sometimes need to move
  2190.          * chars around, and such movement might separate 
  2191.          * the ^ from its following character.
  2192.          */
  2193.         NEW_COLUMN(column+2);
  2194.         *curr++ = (carat_char(c) | 0200);
  2195.         return (0);
  2196.     }
  2197.  
  2198.     /*
  2199.      * Ordinary character.  Just put it in the buffer.
  2200.      */
  2201.     NEW_COLUMN(column+1);
  2202.     *curr++ = c;
  2203.     return (0);
  2204. }
  2205.  
  2206. /*
  2207.  * Analogous to forw_line(), but deals with "raw lines":
  2208.  * lines which are not split for screen width.
  2209.  * {{ This is supposed to be more efficient than forw_line(). }}
  2210.  */
  2211.     public POSITION
  2212. forw_raw_line(curr_pos)
  2213.     POSITION curr_pos;
  2214. {
  2215.     register char *p;
  2216.     register int c;
  2217.     POSITION new_pos;
  2218.  
  2219.     if (curr_pos == NULL_POSITION || ch_seek(curr_pos) ||
  2220.         (c = ch_forw_get()) == EOF)
  2221.         return (NULL_POSITION);
  2222.  
  2223.     p = linebuf;
  2224.  
  2225.     for (;;)
  2226.     {
  2227.         if (c == '\n' || c == EOF)
  2228.         {
  2229.             new_pos = ch_tell();
  2230.             break;
  2231.         }
  2232.         if (p >= &linebuf[sizeof(linebuf)-1])
  2233.         {
  2234.             /*
  2235.              * Overflowed the input buffer.
  2236.              * Pretend the line ended here.
  2237.              * {{ The line buffer is supposed to be big
  2238.              *    enough that this never happens. }}
  2239.              */
  2240.             new_pos = ch_tell() - 1;
  2241.             break;
  2242.         }
  2243.         *p++ = c;
  2244.         c = ch_forw_get();
  2245.     }
  2246.     *p = '\0';
  2247.     line = linebuf;
  2248.     return (new_pos);
  2249. }
  2250.  
  2251. /*
  2252.  * Analogous to back_line(), but deals with "raw lines".
  2253.  * {{ This is supposed to be more efficient than back_line(). }}
  2254.  */
  2255.     public POSITION
  2256. back_raw_line(curr_pos)
  2257.     POSITION curr_pos;
  2258. {
  2259.     register char *p;
  2260.     register int c;
  2261.     POSITION new_pos;
  2262.  
  2263.     if (curr_pos == NULL_POSITION || curr_pos <= (POSITION)0 ||
  2264.         ch_seek(curr_pos-1))
  2265.         return (NULL_POSITION);
  2266.  
  2267.     p = &linebuf[sizeof(linebuf)];
  2268.     *--p = '\0';
  2269.  
  2270.     for (;;)
  2271.     {
  2272.         c = ch_back_get();
  2273.         if (c == '\n')
  2274.         {
  2275.             /*
  2276.              * This is the newline ending the previous line.
  2277.              * We have hit the beginning of the line.
  2278.              */
  2279.             new_pos = ch_tell() + 1;
  2280.             break;
  2281.         }
  2282.         if (c == EOF)
  2283.         {
  2284.             /*
  2285.              * We have hit the beginning of the file.
  2286.              * This must be the first line in the file.
  2287.              * This must, of course, be the beginning of the line.
  2288.              */
  2289.             new_pos = (POSITION)0;
  2290.             break;
  2291.         }
  2292.         if (p <= linebuf)
  2293.         {
  2294.             /*
  2295.              * Overflowed the input buffer.
  2296.              * Pretend the line ended here.
  2297.              */
  2298.             new_pos = ch_tell() + 1;
  2299.             break;
  2300.         }
  2301.         *--p = c;
  2302.     }
  2303.     line = p;
  2304.     return (new_pos);
  2305. }
  2306. SHAR_EOF
  2307. fi
  2308. if test -f 'main.c'
  2309. then
  2310.     echo shar: "will not over-write existing file 'main.c'"
  2311. else
  2312. cat << \SHAR_EOF > 'main.c'
  2313. /*
  2314.  * Entry point, initialization, miscellaneous routines.
  2315.  */
  2316.  
  2317. #include "less.h"
  2318. #include "position.h"
  2319. #include <setjmp.h>
  2320.  
  2321. public int    ispipe;
  2322. public jmp_buf    main_loop;
  2323. public char *    first_cmd;
  2324. public char *    every_first_cmd;
  2325. public int    new_file;
  2326. public int    is_tty;
  2327. public char     current_file[128];
  2328. public int ac;
  2329. public char **av;
  2330. public int curr_ac;
  2331. #if EDITOR
  2332. public char *    editor;
  2333. #endif
  2334.  
  2335. extern int file;
  2336. extern int nbufs;
  2337. extern int sigs;
  2338. extern int quit_at_eof;
  2339. extern int p_nbufs, f_nbufs;
  2340. extern int back_scroll;
  2341. extern int top_scroll;
  2342. extern int sc_height;
  2343.  
  2344.  
  2345. /*
  2346.  * Edit a new file.
  2347.  * Filename "-" means standard input.
  2348.  * No filename means the "current" file, from the command line.
  2349.  */
  2350.     public void
  2351. edit(filename)
  2352.     char *filename;
  2353. {
  2354.     register int f;
  2355.     char message[100];
  2356.     static int any_edited = 0;
  2357.     static int hold_scroll = 0;
  2358.  
  2359.     if (filename == NULL || *filename == '\0')
  2360.     {
  2361.         if (curr_ac >= ac)
  2362.         {
  2363.             error("No current file");
  2364.             return;
  2365.         }
  2366.         filename = av[curr_ac];
  2367.     }
  2368.     if (strcmp(filename, "-") == 0)
  2369.         f = 0;    /* Standard input */
  2370.     else if ((f = open(filename, 0)) < 0)
  2371.     {
  2372.         sprintf(message, "Cannot open %.*s", 
  2373.             error_width()-13, filename);
  2374.         if (any_edited)
  2375.             error(message);
  2376.         else
  2377.         {
  2378.             puts(message);
  2379.             hold_scroll = 1;
  2380.         }
  2381.         return;
  2382.     }
  2383.  
  2384.     if (isatty(f))
  2385.     {
  2386.         /*
  2387.          * Not really necessary to call this an error,
  2388.          * but if the control terminal (for commands)
  2389.          * and the input file (for data) are the same,
  2390.          * we get weird results at best.
  2391.          */
  2392.         error("Can't take input from a terminal");
  2393.         if (f > 0)
  2394.             close(f);
  2395.         return;
  2396.     }
  2397.  
  2398.     /*
  2399.      * Close the current input file and set up to use the new one.
  2400.      */
  2401.     if (file > 0)
  2402.         close(file);
  2403.     new_file = 1;
  2404.     strcpy(current_file, filename);
  2405.     ispipe = (f == 0);
  2406.     file = f;
  2407.     ch_init( (ispipe) ? p_nbufs : f_nbufs );
  2408.     init_mark();
  2409.     if (every_first_cmd != NULL)
  2410.         first_cmd = every_first_cmd;
  2411.     if (is_tty)
  2412.     {
  2413.         any_edited = 1;
  2414.         if (hold_scroll)
  2415.         {
  2416.             /*
  2417.              * Before erasing the screen contents,
  2418.              * display the file name and ask for a keystroke.
  2419.              */
  2420.             error(filename);
  2421.             hold_scroll = 0;
  2422.         }
  2423.         if (first_cmd == NULL || *first_cmd == '\0')
  2424.         {
  2425.             /* 
  2426.              * Display the first screen. 
  2427.              */
  2428.             jump_back(1);
  2429.         } else
  2430.         {
  2431.             /* 
  2432.              * The first_cmd will hopefully redisplay the
  2433.              * screen, so we need not display anything yet.
  2434.              * Indicate there is nothing yet on the screen. 
  2435.              */
  2436.             pos_clear();
  2437.         }
  2438.     }
  2439. }
  2440.  
  2441. /*
  2442.  * Edit the next file in the command line list.
  2443.  */
  2444.     public void
  2445. next_file(n)
  2446.     int n;
  2447. {
  2448.     if (curr_ac + n >= ac)
  2449.     {
  2450.         if (quit_at_eof)
  2451.             quit();
  2452.         error("No (N-th) next file");
  2453.     } else
  2454.         edit(av[curr_ac += n]);
  2455. }
  2456.  
  2457. /*
  2458.  * Edit the previous file in the command line list.
  2459.  */
  2460.     public void
  2461. prev_file(n)
  2462.     int n;
  2463. {
  2464.     if (curr_ac - n < 0)
  2465.         error("No (N-th) previous file");
  2466.     else
  2467.         edit(av[curr_ac -= n]);
  2468. }
  2469.  
  2470. /*
  2471.  * Copy a file directly to standard output.
  2472.  * Used if standard output is not a tty.
  2473.  */
  2474.     static void
  2475. cat_file()
  2476. {
  2477.     register int c;
  2478.  
  2479.     while ((c = ch_forw_get()) != EOF)
  2480.         putc(c);
  2481.     flush();
  2482. }
  2483.  
  2484. /*
  2485.  * Entry point.
  2486.  */
  2487. main(argc, argv)
  2488.     int argc;
  2489.     char *argv[];
  2490. {
  2491.     char *getenv();
  2492.  
  2493.  
  2494.     /*
  2495.      * Process command line arguments and LESS environment arguments.
  2496.      * Command line arguments override environment arguments.
  2497.      */
  2498.     init_option();
  2499.     scan_option(getenv("LESS"));
  2500.     argv++;
  2501.     while ( (--argc > 0) && 
  2502.         (argv[0][0] == '-' || argv[0][0] == '+') && 
  2503.         argv[0][1] != '\0')
  2504.         scan_option(*argv++);
  2505.  
  2506. #if EDITOR
  2507.     editor = getenv("EDITOR");
  2508.     if (editor == NULL || *editor == '\0')
  2509.         editor = EDIT_PGM;
  2510. #endif
  2511.  
  2512.     /*
  2513.      * Set up list of files to be examined.
  2514.      */
  2515.     ac = argc;
  2516.     av = argv;
  2517.     curr_ac = 0;
  2518.  
  2519.     /*
  2520.      * Set up terminal, etc.
  2521.      */
  2522.     is_tty = isatty(1);
  2523.     if (!is_tty)
  2524.     {
  2525.         /*
  2526.          * Output is not a tty.
  2527.          * Just copy the input file(s) to output.
  2528.          */
  2529.         if (ac < 1)
  2530.         {
  2531.             edit("-");
  2532.             cat_file();
  2533.         } else
  2534.         {
  2535.             do
  2536.             {
  2537.                 edit((char *)NULL);
  2538.                 if (file >= 0)
  2539.                     cat_file();
  2540.             } while (++curr_ac < ac);
  2541.         }
  2542.         exit(0);
  2543.     }
  2544.  
  2545.     raw_mode(1);
  2546.     get_term();
  2547.     open_getc();
  2548.     init();
  2549.  
  2550.     if (back_scroll < 0)
  2551.     {
  2552.         /* {{ KLUDGE }} */
  2553.         back_scroll = sc_height-1;
  2554.         if (top_scroll)
  2555.             back_scroll--;
  2556.     }
  2557.  
  2558.     if (setjmp(main_loop))
  2559.         quit();
  2560.     init_signals();
  2561.  
  2562.     /*
  2563.      * Select the first file to examine.
  2564.      */
  2565.     if (ac < 1)
  2566.         edit("-");    /* Standard input */
  2567.     else 
  2568.     {
  2569.         /*
  2570.          * Try all the files named as command arguments.
  2571.          * We are simply looking for one which can be
  2572.          * opened without error.
  2573.          */
  2574.         do
  2575.         {
  2576.             edit((char *)NULL);
  2577.             if (file >= 0)
  2578.                 /* We can open this file. */
  2579.                 break;
  2580.             putc('\n');  flush();
  2581.         } while (++curr_ac < ac);
  2582.     }
  2583.  
  2584.     if (file >= 0)
  2585.         commands();
  2586.     quit();
  2587. }
  2588.  
  2589. /*
  2590.  * Exit the program.
  2591.  */
  2592.     public void
  2593. quit()
  2594. {
  2595.     /*
  2596.      * Put cursor at bottom left corner, clear the line,
  2597.      * reset the terminal modes, and exit.
  2598.      */
  2599.     lower_left();
  2600.     clear_eol();
  2601.     deinit();
  2602.     flush();
  2603.     raw_mode(0);
  2604.     exit(0);
  2605. }
  2606. SHAR_EOF
  2607. fi
  2608. if test -f 'makefile.bsd41'
  2609. then
  2610.     echo shar: "will not over-write existing file 'makefile.bsd41'"
  2611. else
  2612. cat << \SHAR_EOF > 'makefile.bsd41'
  2613. # Makefile for "less"
  2614. #
  2615. # Invoked as:
  2616. #    make all
  2617. #   or    make install
  2618. # Plain "make" is equivalent to "make all".
  2619. #
  2620. # If you add or delete functions, remake funcs.h by doing:
  2621. #    make newfuncs
  2622. # This depends on the coding convention of function headers looking like:
  2623. #    " \t public <function-type> \n <function-name> ( ... ) "
  2624. #
  2625. # Also provided:
  2626. #    make lint    # Runs "lint" on all the sources.
  2627. #    make clean    # Removes "less" and the .o files.
  2628. #    make clobber    # Pretty much the same as make "clean".
  2629. #
  2630. #    make pager_patch        # makes PAGER environment variable
  2631. #    make install_pager_patch    # catcher and installs it (see below)
  2632.  
  2633. ##########################################################################
  2634. # System-specific parameters
  2635. ##########################################################################
  2636.  
  2637. # Define XENIX if running under XENIX 3.0
  2638. XENIX = 0
  2639.  
  2640. # VOID is 1 if your C compiler supports the "void" type,
  2641. # 0 if it does not.
  2642. VOID = 1
  2643.  
  2644. # off_t is the type which lseek() returns.
  2645. # It is also the type of lseek()'s second argument.
  2646. off_t = long
  2647.  
  2648. # TERMIO is 1 if your system has /usr/include/termio.h.
  2649. # This is normally the case for System 5.
  2650. # If TERMIO is 0 your system must have /usr/include/sgtty.h.
  2651. # This is normally the case for BSD.
  2652. TERMIO = 0
  2653.  
  2654. # SIGSETMASK is 1 if your system has the sigsetmask() call.
  2655. # This is normally the case only for BSD 4.2,
  2656. # not for BSD 4.1 or System 5.
  2657. SIGSETMASK = 0
  2658.  
  2659.  
  2660. ##########################################################################
  2661. # Optional and semi-optional features
  2662. ##########################################################################
  2663.  
  2664. # REGCMP is 1 if your system has the regcmp() function.
  2665. # This is normally the case for System 5.
  2666. # RECOMP is 1 if your system has the re_comp() function.
  2667. # This is normally the case for BSD.
  2668. # If neither is 1, pattern matching is supported, but without metacharacters.
  2669. REGCMP = 0
  2670. RECOMP = 1
  2671.  
  2672. # SHELL_ESCAPE is 1 if you wish to allow shell escapes.
  2673. # (This is possible only if your system supplies the system() function.)
  2674. SHELL_ESCAPE = 0
  2675.  
  2676. # EDITOR is 1 if you wish to allow editor invocation (the "v" command).
  2677. # (This is possible only if your system supplies the system() function.)
  2678. # EDIT_PGM is the name of the (default) editor to be invoked.
  2679. EDITOR = 0
  2680. EDIT_PGM = /usr/ucb/vi
  2681.  
  2682. # parameters to "make install_pager_patch".  OLD_PAGER will be moved to
  2683. # OLD_PAGER_NEW_LOCATION and pager_patch (in this directory) will be installed
  2684. # as OLD_PAGER.  This patch will allow you to set the environment variable
  2685. # PAGER to specify your personal pager preference (is this a security hole?)
  2686. OLD_PAGER = /usr/ucb/more
  2687. OLD_PAGER_NEW_LOCATION = /usr/ucb/More
  2688.  
  2689. # ONLY_RETURN is 1 if you want RETURN to be the only input which
  2690. # will continue past an error message.
  2691. # Otherwise, any key will continue past an error message.
  2692. ONLY_RETURN = 0
  2693.  
  2694.  
  2695. ##########################################################################
  2696. # Compilation environment.
  2697. ##########################################################################
  2698.  
  2699. # LIBS is the list of libraries needed.
  2700. LIBS = -ltermcap
  2701.  
  2702. # INSTALL_LESS is a list of the public versions of less.
  2703. # INSTALL_MAN is a list of the public versions of the manual page.
  2704. INSTALL_LESS =    /usr/local/less
  2705. INSTALL_MAN =    /usr/man/manl/less.l
  2706.  
  2707. # OPTIM is passed to the compiler and the loader.
  2708. # It is normally "-O" but may be, for example, "-g".
  2709. OPTIM = -O
  2710.  
  2711.  
  2712. ##########################################################################
  2713. # Files
  2714. ##########################################################################
  2715.  
  2716. SRC1 =    main.c option.c prim.c 
  2717. SRC2 =    ch.c position.c input.c output.c screen.c \
  2718.     prompt.c line.c signal.c help.c ttyin.c command.c version.c
  2719. SRC =    $(SRC1) $(SRC2)
  2720. OBJ =    main.o option.o prim.o ch.o position.o input.o output.o screen.o \
  2721.     prompt.o line.o signal.o help.o ttyin.o command.o version.o
  2722.  
  2723.  
  2724. ##########################################################################
  2725. # Rules
  2726. ##########################################################################
  2727.  
  2728. DEFS =    "-DTERMIO=$(TERMIO)" \
  2729.     "-DSIGSETMASK=$(SIGSETMASK)" \
  2730.     "-Doff_t=$(off_t)" "-DVOID=$(VOID)" \
  2731.     "-DREGCMP=$(REGCMP)" "-DRECOMP=$(RECOMP)" \
  2732.     "-DSHELL_ESCAPE=$(SHELL_ESCAPE)" \
  2733.     "-DEDITOR=$(EDITOR)" "-DEDIT_PGM=\"$(EDIT_PGM)\"" \
  2734.     "-DONLY_RETURN=$(ONLY_RETURN)" \
  2735.     "-DXENIX=$(XENIX)" \
  2736.     "-DOLD_PAGER_NEW_LOCATION=\"$(OLD_PAGER_NEW_LOCATION)\""
  2737.  
  2738. CFLAGS = $(OPTIM) $(DEFS)
  2739.  
  2740.  
  2741. all: less
  2742.  
  2743. less: $(OBJ)
  2744.     cc $(OPTIM) -o less $(OBJ) $(LIBS)
  2745.  
  2746. install: install_man install_less
  2747.  
  2748. install_man: less.l
  2749.     for f in $(INSTALL_MAN); do  rm -f $$f; cp less.l $$f;  done
  2750.     touch install_man
  2751.     
  2752. install_less: less
  2753.     for f in $(INSTALL_LESS); do  rm -f $$f; cp less $$f;  done
  2754.     touch install_less
  2755.  
  2756. pager_patch: pager_patch.c
  2757.     cc $(CFLAGS) -s -o pager_patch pager_patch.c
  2758.  
  2759. install_pager_patch: pager_patch
  2760.     if [ -s $(OLD_PAGER) -a ! -s $(OLD_PAGER_NEW_LOCATION) ]; then \
  2761.         mv $(OLD_PAGER) $(OLD_PAGER_NEW_LOCATION); \
  2762.         cp pager_patch $(OLD_PAGER); \
  2763.     fi
  2764.     touch install_pager_patch
  2765.  
  2766. $(OBJ): less.h funcs.h
  2767.  
  2768. lint:
  2769.     lint -hp $(DEFS) $(SRC)
  2770.  
  2771. newfuncs:
  2772.     mv funcs.h funcs.h.OLD
  2773.     awk -f mkfuncs.awk $(SRC) >funcs.h
  2774.  
  2775. clean:
  2776.     rm -f $(OBJ) less pager_patch
  2777.  
  2778. clobber:
  2779.     rm -f *.o less pager_patch install_less install_man install_pager_patch
  2780.  
  2781. shar:
  2782.     shar -v INSTALLATION less.l makefile.* *.h *.awk $(SRC1) > less.shar.a
  2783.     shar -v $(SRC2) pager_patch.c > less.shar.b
  2784. SHAR_EOF
  2785. fi
  2786. if test -f 'makefile.bsd42'
  2787. then
  2788.     echo shar: "will not over-write existing file 'makefile.bsd42'"
  2789. else
  2790. cat << \SHAR_EOF > 'makefile.bsd42'
  2791. # Makefile for "less"
  2792. #
  2793. # Invoked as:
  2794. #    make all
  2795. #   or    make install
  2796. # Plain "make" is equivalent to "make all".
  2797. #
  2798. # If you add or delete functions, remake funcs.h by doing:
  2799. #    make newfuncs
  2800. # This depends on the coding convention of function headers looking like:
  2801. #    " \t public <function-type> \n <function-name> ( ... ) "
  2802. #
  2803. # Also provided:
  2804. #    make lint    # Runs "lint" on all the sources.
  2805. #    make clean    # Removes "less" and the .o files.
  2806. #    make clobber    # Pretty much the same as make "clean".
  2807. #
  2808. #    make pager_patch        # makes PAGER environment variable
  2809. #    make install_pager_patch    # catcher and installs it (see below)
  2810.  
  2811.  
  2812. ##########################################################################
  2813. # System-specific parameters
  2814. ##########################################################################
  2815.  
  2816. # Define XENIX if running under XENIX 3.0
  2817. XENIX = 0
  2818.  
  2819. # VOID is 1 if your C compiler supports the "void" type,
  2820. # 0 if it does not.
  2821. VOID = 1
  2822.  
  2823. # off_t is the type which lseek() returns.
  2824. # It is also the type of lseek()'s second argument.
  2825. off_t = long
  2826.  
  2827. # TERMIO is 1 if your system has /usr/include/termio.h.
  2828. # This is normally the case for System 5.
  2829. # If TERMIO is 0 your system must have /usr/include/sgtty.h.
  2830. # This is normally the case for BSD.
  2831. TERMIO = 0
  2832.  
  2833. # SIGSETMASK is 1 if your system has the sigsetmask() call.
  2834. # This is normally the case only for BSD 4.2,
  2835. # not for BSD 4.1 or System 5.
  2836. SIGSETMASK = 1
  2837.  
  2838.  
  2839. ##########################################################################
  2840. # Optional and semi-optional features
  2841. ##########################################################################
  2842.  
  2843. # REGCMP is 1 if your system has the regcmp() function.
  2844. # This is normally the case for System 5.
  2845. # RECOMP is 1 if your system has the re_comp() function.
  2846. # This is normally the case for BSD.
  2847. # If neither is 1, pattern matching is supported, but without metacharacters.
  2848. REGCMP = 0
  2849. RECOMP = 1
  2850.  
  2851. # SHELL_ESCAPE is 1 if you wish to allow shell escapes.
  2852. # (This is possible only if your system supplies the system() function.)
  2853. SHELL_ESCAPE = 0
  2854.  
  2855. # EDITOR is 1 if you wish to allow editor invocation (the "v" command).
  2856. # (This is possible only if your system supplies the system() function.)
  2857. # EDIT_PGM is the name of the (default) editor to be invoked.
  2858. EDITOR = 0
  2859. EDIT_PGM = /usr/ucb/vi
  2860.  
  2861. # parameters to "make install_pager_patch".  OLD_PAGER will be moved to
  2862. # OLD_PAGER_NEW_LOCATION and pager_patch (in this directory) will be installed
  2863. # as OLD_PAGER.  This patch will allow you to set the environment variable
  2864. # PAGER to specify your personal pager preference (is this a security hole?)
  2865. OLD_PAGER = /usr/ucb/more
  2866. OLD_PAGER_NEW_LOCATION = /usr/ucb/More
  2867.  
  2868. # ONLY_RETURN is 1 if you want RETURN to be the only input which
  2869. # will continue past an error message.
  2870. # Otherwise, any key will continue past an error message.
  2871. ONLY_RETURN = 0
  2872.  
  2873.  
  2874. ##########################################################################
  2875. # Compilation environment.
  2876. ##########################################################################
  2877.  
  2878. # LIBS is the list of libraries needed.
  2879. LIBS = -ltermcap
  2880.  
  2881. # INSTALL_LESS is a list of the public versions of less.
  2882. # INSTALL_MAN is a list of the public versions of the manual page.
  2883. INSTALL_LESS =    /usr/local/less
  2884. INSTALL_MAN =    /usr/man/manl/less.l
  2885.  
  2886. # OPTIM is passed to the compiler and the loader.
  2887. # It is normally "-O" but may be, for example, "-g".
  2888. OPTIM = -O
  2889.  
  2890.  
  2891. ##########################################################################
  2892. # Files
  2893. ##########################################################################
  2894.  
  2895. SRC1 =    main.c option.c prim.c
  2896. SRC2 =    ch.c position.c input.c output.c screen.c \
  2897.     prompt.c line.c signal.c help.c ttyin.c command.c version.c
  2898. SRC =    $(SRC1) $(SRC2)
  2899. OBJ =    main.o option.o prim.o ch.o position.o input.o output.o screen.o \
  2900.     prompt.o line.o signal.o help.o ttyin.o command.o version.o
  2901.  
  2902.  
  2903. ##########################################################################
  2904. # Rules
  2905. ##########################################################################
  2906.  
  2907. DEFS =    "-DTERMIO=$(TERMIO)" \
  2908.     "-DSIGSETMASK=$(SIGSETMASK)" \
  2909.     "-Doff_t=$(off_t)" "-DVOID=$(VOID)" \
  2910.     "-DREGCMP=$(REGCMP)" "-DRECOMP=$(RECOMP)" \
  2911.     "-DSHELL_ESCAPE=$(SHELL_ESCAPE)" \
  2912.     "-DEDITOR=$(EDITOR)" "-DEDIT_PGM=\"$(EDIT_PGM)\"" \
  2913.     "-DONLY_RETURN=$(ONLY_RETURN)" \
  2914.     "-DXENIX=$(XENIX)" \
  2915.     "-DOLD_PAGER_NEW_LOCATION=\"$(OLD_PAGER_NEW_LOCATION)\""
  2916.  
  2917. CFLAGS = $(OPTIM) $(DEFS)
  2918.  
  2919.  
  2920. all: less
  2921.  
  2922. less: $(OBJ)
  2923.     cc $(OPTIM) -o less $(OBJ) $(LIBS)
  2924.  
  2925. install: install_man install_less
  2926.  
  2927. install_man: less.l
  2928.     for f in $(INSTALL_MAN); do  rm -f $$f; cp less.l $$f;  done
  2929.     touch install_man
  2930.     
  2931. install_less: less
  2932.     for f in $(INSTALL_LESS); do  rm -f $$f; cp less $$f;  done
  2933.     touch install_less
  2934.  
  2935. pager_patch: pager_patch.c
  2936.     cc $(CFLAGS) -s -o pager_patch pager_patch.c
  2937.  
  2938. install_pager_patch: pager_patch
  2939.     if [ -s $(OLD_PAGER) -a ! -s $(OLD_PAGER_NEW_LOCATION) ]; then \
  2940.         mv $(OLD_PAGER) $(OLD_PAGER_NEW_LOCATION); \
  2941.         cp pager_patch $(OLD_PAGER); \
  2942.     fi
  2943.     touch install_pager_patch
  2944.  
  2945. $(OBJ): less.h funcs.h
  2946.  
  2947. lint:
  2948.     lint -hp $(DEFS) $(SRC)
  2949.  
  2950. newfuncs:
  2951.     mv funcs.h funcs.h.OLD
  2952.     awk -f mkfuncs.awk $(SRC) >funcs.h
  2953.  
  2954. clean:
  2955.     rm -f $(OBJ) less pager_patch
  2956.  
  2957. clobber:
  2958.     rm -f *.o less pager_patch install_less install_man install_pager_patch
  2959.  
  2960. shar:
  2961.     shar -v INSTALLATION less.l makefile.* *.h *.awk $(SRC1) > less.shar.a
  2962.     shar -v $(SRC2) pager_patch.c > less.shar.b
  2963. SHAR_EOF
  2964. fi
  2965. exit 0
  2966. #    End of shell archive
  2967.  
  2968.  
  2969.